'How to build a tree using LazyColumn in Jetpack Compose?
In my jetpack-compose app, I'm building a comment tree, where the top level, and the leaves, are lists, that would be best to use LazyColumn.
This is of the form:
List<CommentNode>
...
CommentNode: {
content: String
children: List<CommentNode>
}
@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)
}
}
}
On the top level, LazyColumn works, but it seems I have to use Column for the leaves, otherwise I get an unexplained crash:
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!
Has anyone had any luck building a variable length tree in jetpack compose?
Solution 1:[1]
I don't think you really need to place one LazyColumn into an other one - each of them gonna have it's own scroll logic.
Instead you can place item for each node recursively. To do this, declare your function on LazyListScope. These are no longer views, since the views will be inside item. And I think the lowercase naming would be correct here.
@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,
)
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
