Developing a messenger app UI and got a last minute requirement to support grid layouts. Due to the way I structured the messenger container screen, I can't use LVGL because the root parent view containing the messages is a LazyColumn. Creating a grid manually is straightforward enough, but I'm not sure how to handle the last line of content where there aren't enough elements to fill out the row. I want to be able to count on composition to automatically size the button to the same dimensions as the buttons in the full rows so that the columns are lined up.

Currently, my implementation passes Row modifier with weight of 1f to each button in grid row. If there aren't enough elements to fill out a row, I create invisible and unclickable duplicates of the first element in that row to fill it out.
My understanding about how the measuring works is really weak. What is a more organic way of getting composition to resize buttons the way I want even if there aren't enough elements to warrant it?
Alternatively, if there's a way to handle LazyVerticalGridLayout so that I can use it with a parent LazyColumn with minimal adjustments, that would work too?
In Compose version 1.4.0-rc01, there is a new structures called FlowRow and FlowColumn, In your case, you need FlowRow. To make it simple, it place elements on the screen, and in case there is not enough space for the next, it will continue on the following line, as said in the documentation:
FlowRow is a layout that fills items from left to right (ltr) in LTR layouts or right to left (rtl) in RTL layouts and when it runs out of space, moves to the next "row" or "line" positioned on the bottom, and then continues filling items until the items run out.
I think it is very good in your case, you can use it to create a non-lazy grid, and it works inside LazyColumn too, so you will not have problems with your current layout. I will show you a simple example of how to use it:
@Composable
fun ClockButton(
modifier: Modifier = Modifier,
clock: String,
onClick: () -> Unit
) {
OutlinedButton(
modifier = modifier,
onClick = onClick,
border = BorderStroke(2.dp, Color.Red)
) {
Text(text = clock, color = Color.Red)
}
}
@OptIn(ExperimentalLayoutApi::class)
@Composable
fun Grid() {
LazyColumn(
modifier = Modifier.fillMaxSize().padding(16.dp),
verticalArrangement = Arrangement.Center
) {
item {
Text(
modifier = Modifier.padding(bottom = 16.dp),
text = "Morning",
style = MaterialTheme.typography.titleMedium
)
}
item {
FlowRow(
horizontalArrangement = Arrangement.spacedBy(16.dp),
) {
ClockButton(
clock = "10:00 AM",
onClick = {}
)
ClockButton(
clock = "10:30 AM",
onClick = {}
)
ClockButton(
clock = "11:00 AM",
onClick = {}
)
ClockButton(
clock = "11:30 AM",
onClick = {}
)
}
}
}
}
Result:

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With