You can use subcompose layout to precalculate the max height of the biggest view, and then use that height for all of the LazyVerticalGrid items.
For example:

How does this work?
SubcomposeLayout gives you constraints, i.e. the max width and height the view could be. You can use this to calculate how many views will fit for a given min width. I will use 128 dp:
val longestText = exampleStringList.maxBy { it.length }
val maxWidthDp = constraints.maxWidth/1.dp.toPx()
val width = maxWidthDp/floor(maxWidthDp/128)
Then you can measure the height of a test view, in my case CategoryButton passing the calculated width from above to the modifier:
val measuredHeight = subcompose("viewToMeasure") {
CategoryButton(
longestText,
modifier = Modifier.width(width.dp)
)
}[0]
.measure(Constraints()).height.toDp()
Next you compose your actual LazyVerticalGrid, ensuring that the items use the height you calculated above:
val contentPlaceable = subcompose("content") {
LazyVerticalGrid(
columns = GridCells.Adaptive(minSize = 128.dp),
verticalArrangement = Arrangement.spacedBy(12.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
items(DataStore.categories) { category ->
CategoryButton(
category,
onClick = { onCategorySelected(category) },
modifier = Modifier.height(measuredHeight)
)
}
}
}[0].measure(constraints)
And finally, layout the LazyVerticalGrid:
layout(contentPlaceable.width, contentPlaceable.height) {
contentPlaceable.place(0, 0)
}
Full code:
SubcomposeLayout { constraints ->
val longestText = DataStore.categories.maxBy { it.length }
val maxWidthDp = constraints.maxWidth/1.dp.toPx()
val width = maxWidthDp/floor(maxWidthDp/128)
val measuredHeight = subcompose("viewToMeasure") {
CategoryButton(
longestText,
modifier = Modifier.width(width.dp)
)
}[0]
.measure(Constraints()).height.toDp()
val contentPlaceable = subcompose("content") {
LazyVerticalGrid(
columns = GridCells.Adaptive(minSize = 128.dp),
verticalArrangement = Arrangement.spacedBy(12.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
items(DataStore.categories) { category ->
CategoryButton(
category,
onClick = { onCategorySelected(category) },
modifier = Modifier.height(measuredHeight)
)
}
}
}[0].measure(constraints)
layout(contentPlaceable.width, contentPlaceable.height) {
contentPlaceable.place(0, 0)
}
}