What can I do if I need to put a lazycolumn
inside a lazycolumn
? I'm getting this error:
IllegalStateException: Vertically scrollable component was measured with an infinity maximum height constraints, which is disallowed.
I know that as doc says (https://developer.android.com/develop/ui/compose/lists#avoid-nesting-scrollable), we must avoid nesting components scrollable in the same direction.
But my app is an special app, like an "app constructor" in which the user can construct an app using different types of items, for example: texts, images, vertical scroll containers (lazycolumns
), horizontal scroll containers (lazyrows
), etc and for example, the user is free to put a vertical scroll, with some text and an horizontall scroll, and that horizontal scroll can have a verticall scroll inside.
I need to know how to achieve this
You can put a LazyColumn
into another LazyColumn
or any other Composable with scroll
Modifier but you can't have nested scrollable Composable with Constraints with maxWidth/Height equal to Constraints.Infinity
in scroll direction because scroll Modifier has a check if incoming Constrains have max Constraints.Infinity
. If you change this infinite Constraints.Infinity
to something finite you can put a scrollable inside another one.
I used LazyColumn
in snippets but this answer is about putting a scrollable into another scrollable, no matter which one both are, to have nested scrollable if you ever nested scrollable Composables. If you are using LazyColumn/Row
, etc. you should use items
or item
but in some cases that you might need nested scrollable Composable then you can check section below.
Setting heightIn(max)
to finite changes maxHeight(this is biggest height a Composable can be measured with) nested scrollable Composable can be measured between min-max so it can be as big as its content or you can set a fixed height to limit nested Composable so it does not crash with
java.lang.IllegalStateException: Vertically scrollable component was measured with an infinity maximum height constraints, which is disallowed. One of the common reasons is nesting layouts like LazyColumn and Column(Modifier.verticalScroll()). If you want to add a header before the list of items please add a header as a separate item() before the main items() inside the LazyColumn scope. There are could be other reasons for this to happen: your ComposeView was added into a LinearLayout with some weight, you applied Modifier.wrapContentSize(unbounded = true) or wrote a custom layout. Please try to remove the source of infinite constraints in the hierarchy above the scrolling container.
@Preview
@Composable
fun ScrollTest() {
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
item {
Box(modifier = Modifier.fillMaxWidth().height(200.dp).background(Color.Red))
}
item {
LazyColumn(
modifier = Modifier
// without this modifier crash happens
.heightIn(
// This number is an arbitrary height for demonstration, you can use screen height or
// another number to limit how big this LazyColumn should be
max = Short.MAX_VALUE.toInt().dp
),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
items(20) {
Text(
text = "Nested Row $it",
modifier = Modifier.fillMaxWidth().padding(16.dp)
)
}
}
}
items(20) {
Text(
text = "Outer Row $it",
modifier = Modifier.fillMaxWidth().padding(16.dp)
)
}
}
}
This max number presents how tall LazyColumn
can be. The bigger it is the more items will be composed at once and it will be less lazier more like Column with scroll.
LazyColumn(
modifier = Modifier
// without this modifier crash happens
.heightIn(
max = Short.MAX_VALUE.toInt().dp
),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
items(2000) {
LaunchedEffect(Unit) {
println("Recomposing item: $it")
}
Text(
text = "Nested Row $it",
modifier = Modifier.fillMaxWidth().padding(16.dp)
)
}
}
Composes 582 on my emulator. And that's why there is a warning in the link i shared about performance.
This approach is useful when you don't know 5-10 item long LazyColumn can be, and using big number to measure it's height between 0 and some big number to get content height or putting a LazyGrid with small number of items into a LazyColumn instead of implementing it yourself.
When you wish to put a LazyList into another one consider the fact that depending how big its viewport is number of items it composes changes also.