Jetpack Compose: filling max width or height

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")
        }
    }
}
The Box height is too long in this case

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")
        }
    }
}
Box height is wrapping the 2 Text composables

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!