I am working with a vertical 2-column grid in Jetpack Compose. Each cell can contain a complex set of composables (refer to DynamicGridCell below). However, the height of each cell is set to wrapContent.
My goal is to align items in each row by the height of the tallest item within that row. In other words, all cells in a row should have the same height, matching the tallest cell in that row.
A visual example of the issue, I highlighted the result I need to achieve:
Code Example Here's an example to illustrate the setup:
@Composable
fun DynamicLazyGridScreen(modifier: Modifier = Modifier) {
DynamicLazyGrid(elements = items, modifier = modifier)
}
@Composable
fun DynamicLazyGrid(elements: List<Item>, modifier: Modifier = Modifier) {
LazyVerticalGrid(
columns = GridCells.Fixed(2),
modifier = modifier.fillMaxSize(),
contentPadding = PaddingValues(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
items(elements) {
DynamicGridCell(it, modifier = Modifier)
}
}
}
@Composable
private fun DynamicGridCell(item: Item, modifier: Modifier = Modifier) {
Card(
modifier = Modifier.height(IntrinsicSize.Max)
) {
Column(
modifier = modifier.heightIn(min = 300.dp, max = Dp.Infinity)
) {
Box(
modifier = Modifier
.height(100.dp)
.fillMaxWidth()
.background(color = Color.Green),
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = item.title,
modifier = Modifier
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = item.description,
modifier = Modifier
.padding(8.dp)
.fillMaxHeight()
)
}
}
}
val items = List(50) { i ->
Item(
title = "Title ${i + 1}",
description = "${generateRandomString()} ${i + 1}",
)
}
fun generateRandomString(): String {
val length = Random.nextInt(5, 300)
val chars = ('a'..'z') + ('A'..'Z') + ('0'..'9') // Characters to choose from
return (1..length)
.map { chars.random() }
.joinToString("")
}
data class Item(
val title: String,
val description: String,
)
Update: This question is not similar to How to level the height of items in LazyVerticalGrid? because, in my case, I have a more complex cell, not just an image with a text.
This is the best hacky way of doing it in my opinion without measuring after and doing recompositions etc etc. So you can set the opacity of the adjacent cell to 0f that way you have the same height in each row ;)
The code:
@Composable
fun DynamicLazyGridScreen(modifier: Modifier = Modifier) {
DynamicLazyGrid(items, modifier)
}
@Composable
fun DynamicLazyGrid(elements: List<Item>, modifier: Modifier = Modifier) {
LazyVerticalGrid(
columns = GridCells.Fixed(2),
modifier = modifier.fillMaxSize(),
contentPadding = PaddingValues(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
itemsIndexed(elements) { index, item ->
val backItem = when {
index == 0 -> elements[index + 1]
index == elements.size - 1 -> elements[index - 1]
index % 2 == 0 -> elements[index + 1]
else -> elements[index - 1]
}
DynamicGridCell(
frontItem = item,
backItem = backItem,
modifier = Modifier
)
}
}
}
@Composable
private fun DynamicGridCell(
modifier: Modifier = Modifier,
frontItem: Item,
backItem: Item
) {
Card(modifier = Modifier.height(IntrinsicSize.Max)) {
Box {
StrangeItem(modifier.alpha(0f), backItem)
StrangeItem(modifier.alpha(1f), frontItem)
}
}
}
@Composable
private fun StrangeItem(modifier: Modifier, item: Item) {
Column(
modifier = modifier.heightIn(min = 300.dp)
) {
Box(
modifier = Modifier
.height(100.dp)
.fillMaxWidth()
.background(Color.Green)
)
Spacer(modifier = Modifier.height(4.dp))
Text(text = item.title)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = item.description,
modifier = Modifier
.padding(8.dp)
.fillMaxHeight()
)
}
}
val items = List(50) { index ->
Item(
title = "Title ${index + 1}",
description = "${generateRandomString()} ${index + 1}"
)
}
fun generateRandomString(): String {
val length = Random.nextInt(5, 300)
val chars = ('a'..'z') + ('A'..'Z') + ('0'..'9')
return List(length) { chars.random() }.joinToString("")
}
data class Item(
val title: String,
val description: String
)