如何在 Jetpack Compose 中使用 LazyColumn 构建树?

tho*_*iha 7 android android-jetpack-compose

在我的 jetpack-compose 应用程序中,我正在构建一个注释树,其中顶层和叶子是列表,最好使用LazyColumn.

其形式如下:

List<CommentNode>
...
CommentNode: {
  content: String
  children: List<CommentNode>
}
Run Code Online (Sandbox Code Playgroud)
@Composable
fun Nodes(nodes: List<CommentNode>) {
  LazyColumn {
    items(nodes) { node -> 
      Node(node)
    }
  }
}

@Composable
fun Node(node: CommentNode) {
  LazyColumn {
    item {
      Text(node.content)
    }
    item {
      Nodes(node.children)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

在顶层,LazyColumn可以工作,但似乎我必须用于Column叶子,否则我会遇到无法解释的崩溃:

03-29 14:36:38.792  1658  6241 W ActivityTaskManager:   Force finishing activity com.jerboa/.MainActivity 
03-29 14:36:38.902  1658  3033 I WindowManager: WIN DEATH: Window{d3b902b u0 com.jerboa/com.jerboa.MainActivity}                      
03-29 14:36:38.902  1658  3033 W InputManager-JNI: Input channel object 'd3b902b com.jerboa/com.jerboa.MainActivity (client)' was disposed without first being removed with the input manager!
Run Code Online (Sandbox Code Playgroud)

有没有人有幸在jetpack compose中构建了可变长度的树?

Phi*_*hov 12

我不认为你真的需要将一个元素LazyColumn放入另一个元素中 - 每个元素都有自己的滚动逻辑。

相反,您可以item递归地放置每个节点。为此,请在 上声明您的函数LazyListScope。这些不再是视图,因为视图将位于内部item。我认为这里小写命名是正确的。

@Composable
fun View(nodes: List<CommentNode>) {
    val expandedItems = remember { mutableStateListOf<CommentNode>() }
    LazyColumn {
        nodes(
            nodes,
            isExpanded = {
                expandedItems.contains(it)
            },
            toggleExpanded = {
                if (expandedItems.contains(it)) {
                    expandedItems.remove(it)
                } else {
                    expandedItems.add(it)
                }
            },
        )
    }
}

fun LazyListScope.nodes(
    nodes: List<CommentNode>,
    isExpanded: (CommentNode) -> Boolean,
    toggleExpanded: (CommentNode) -> Unit,
) {
    nodes.forEach { node ->
        node(
            node,
            isExpanded = isExpanded,
            toggleExpanded = toggleExpanded,
        )
    }
}

fun LazyListScope.node(
    node: CommentNode,
    isExpanded: (CommentNode) -> Boolean,
    toggleExpanded: (CommentNode) -> Unit,
) {
    item {
        Text(
            node.content,
            Modifier.clickable {
                toggleExpanded(node)
            }
        )
    }
    if (isExpanded(node)) {
        nodes(
            node.children,
            isExpanded = isExpanded,
            toggleExpanded = toggleExpanded,
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @thouliha `remember` 不应该在 `item` 中使用,因为它会在项目滚出屏幕后被清除。它应该存储在“LazyColumn”之外,请参阅更新的答案如何做到这一点。 (2认同)
  • 我现在在我的代码库中使用它,效果很好。非常感谢! (2认同)