Akram Hussain
Akram Hussain

Reputation: 480

Jetpack Compose Nested LazyColumn

How do I build this UI in Jetpack Compose? Assuming I will need a lazy column for the filter titles and then another nested lazy column for the actual filters but since the jetpack compose doesn't allow nested lazy column what's the alternative way to build it?

Even if I specify the height for the second or first lazy column the content inside may not fit.

Filter layout

Upvotes: 4

Views: 6928

Answers (1)

Sky
Sky

Reputation: 757

Edit: It is better to use the option suggested by Phil Dukhov, link to comment.

Hacky one: You can hack by adding nested Column. Take a look at the pseudocode:

@Composable
fun Screen(
    items: List<Item>,
) {
    // Here we store each state of expandable item
    val expandStates = remember(items.size) {
        List(items.size) { mutableStateOf(false) }
    }

    LazyColumn {
        itemsIndexed(items, { _, it -> it.key }) { idx, item ->
            ExpandableItem(
                modifier = Modifier.fillMaxWidth(),
                item = item.expandable,
                isExpanded = expandStates[idx].value,
            )
        }
    }
}

@Composable
private fun ExpandableItem(
    item: Item,
    isExpanded: Boolean,
    modifier: Modifier = Modifier,
) {
    Column(modifier = modifier.animateContentSize()) {
        Row(
            modifier = Modifier.height(50.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(modifier = Modifier.weight(1f), text = item.title)
            val icon = if (isExpanded) R.drawable.ic_minus else R.drawable.ic_plus
            Icon(
                modifier = Modifier.padding(horizontal = 16.dp),
                painter = painterResource(icon),
                contentDescription = null
            )
        }
        if (isExpanded) Column {
            item.values.forEach { item ->
                ValueItem(
                    modifier = Modifier.fillMaxWidth(),
                    item = item,
                )
            }
        }
    }
}

@Composable
private fun ValueItem(
    item: Item,
    modifier: Modifier = Modifier,
) {
    Column(modifier = modifier) {
        Row(
            modifier = Modifier
                .height(50.dp)
                .padding(start = 16.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(
                modifier = Modifier.weight(1f),
                text = item.name,
                maxLines = 1,
                overflow = TextOverflow.Ellipsis
            )
        }
    }
}

In example above Item represent some abstract content for you specific case.

Upvotes: 4

Related Questions