I am working on a screen that has a Column where I...
# compose
j
I am working on a screen that has a Column where I need the height of each item in the Column to be the same. I’ve tried searching here and in SO and I’m not coming up with anything concrete. Does anyone have a good example or standard way of accomplishing this? More info in 🧵
The code is something like this:
Copy code
Column {
    Row(
       modifier = Modifier.fillMaxWidth()
    ) {
        CheckBox(...)
        Text(...)
    }
}
Essentially there’s cases where the text can wrap and I want to make all the rows the same height when that happens.
f
j
from my understanding intrinsics works well when the Height needs to be the same for items in a row, or the width needs to be the same for items in a column, but I haven’t been able to get it to work for the height of items in a column.
f
I see, in that case you may need to use a
Layout
and query the children's desired height, then use constrains with fixed dimensions to measure them all with
oh wait, what about
weight
? just set the same weight to all children
j
yeah, I tried weight. Weight makes them all the same size but it makes them stretch the height of the entire column so it takes up the whole screen. That could work if I knew what max height to set the column to but that would require me to know the height of the tallest row anyway and then do the math for the max height.
Maybe if I set the weight ratio properly that’ll work though. I’ll try that
f
you can do this
Copy code
@Composable
fun MyColumn(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit,
) {
    Layout(
        modifier = modifier,
        content = content,
    ) { measurables, constraints ->
        val itemHeight = measurables.maxOfOrNull { measurable ->
            measurable.maxIntrinsicHeight(width = constraints.maxWidth)
        } ?: 0
        val itemConstraints = Constraints(
            minWidth = 0,
            maxWidth = constraints.maxWidth,
            minHeight = itemHeight,
            maxHeight = itemHeight,
        )
        val placeables = measurables.map { measurable -> measurable.measure(itemConstraints) }
        layout(
            width = constraints.maxWidth,
            height = measurables.size * itemHeight,
        ) {
            placeables.forEachIndexed { index, placeable ->
                placeable.placeRelative(
                    x = 0,
                    y = index * itemHeight,
                )
            }
        }
    }
}
which you use like this
Copy code
MyTheme {
        Surface(color = Theme.colors.background) {
            MyColumn(modifier = Modifier.fillMaxWidth().height(300.dp)) {
                Text(
                    text = "Foobar",
                    modifier = Modifier.fillMaxWidth().background(Color.Red.copy(alpha = .3f)),
                )
                Text(
                    text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc metus ante, hendrerit at erat ornare, molestie sollicitudin dui. Sed porttitor a nisl vel ullamcorper. Vivamus sodales augue et dui volutpat, eu pharetra augue tincidunt",
                    modifier = Modifier.fillMaxWidth().background(Color.Blue.copy(alpha = .3f)),
                )
                Text(
                    text = "BarBaz",
                    modifier = Modifier.fillMaxWidth().background(Color.Red.copy(alpha = .3f)),
                )
            }
        }
    }
j
Wow, that’s great! Thanks! I’ll try that out
Thanks again @Francesc! This works great for me except when I use MyColumn within a LazyColumn. I think the intrinsic heights get messed up by the outer lazy column so I’m looking into that.
f
within a LazyColumn the constraints for height would be infinite, so that could be messing up the measurements
j
yeah, that’s what I was thinking, but not sure if there’s any way to work around that
Ah! Got it working. My items that are inside “MyColumn” are not just a text but something like this:
Copy code
Column {
    Row {
        Checkbox(...)
        Text(...)
    }
    Divider(...)
}
If I set the height of the internal column and row to be Intrinsic.Min then it works as expected
Makes sense because that gives MyColumn enough guidance to set a limit on the height even though it’s within a LazyColumn.
actually just setting it on the internal column is sufficient