One interesting thing about Jetpack Compose is this: it only measures children in layouts once. Measuring children in layouts twice will throw a runtime exception according to the documentation.
I guess this helps with quickly rendering things on the screen. But it has some additional consequences: if you have a layout that depends on dynamic width/height how do you get the final width/height after the content is set?
Let me give you an example. You want a vertical filled line next to 2 vertical texts. Easy right? You just use a Row
, a Column
and a Box
like this (check this out for the basic layouts):
@Composable
fun content() {
return Row {
Box(
modifier = Modifier
.width(8.dp)
.fillMaxHeight()
.background(Color.Red)
)
Column {
Text("Hello")
Text("World")
}
}
}
Why is this so long? We explicitly asked for fillMaxHeight()
meaning the max combined height of the 2 Text
composables.
As explained in the intro, compose measures the Row
children individually only once, and at the time of drawing the Box
it doesn't know the max available height of the 2 Text
composables.
This can be fixed by adding height(IntrinsicSize.Min)
to the Row
parent composable:
@Composable
fun content() {
return Row(
modifier = Modifier
.height(IntrinsicSize.Min)
) {
Box(
modifier = Modifier
.width(8.dp)
.fillMaxHeight()
.background(Color.Red)
)
Column {
Text("Hello")
Text("World")
}
}
}
This modifier forces the Row
children to use their minimum intrinsic size. When measuring is taking place, now Compose has enough info to calculate fillMaxHeight()
for the Box
.
Hopefully, by now you have figured out why Compose is laying your composables with too long heights (or no height at all if trying to use fillMaxHeight
inside a LazyList
).
Happy coding!
Top comments (0)