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.
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.
Share Improve this question edited Nov 21, 2024 at 9:22 Oleksii Shtanko asked Nov 20, 2024 at 21:43 Oleksii ShtankoOleksii Shtanko 2154 silver badges12 bronze badges 2- This question is similar to: How to level the height of items in LazyVerticalGrid?. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. – tyg Commented Nov 21, 2024 at 0:04
- @tyg, thanks for the comment, I have updated the question – Oleksii Shtanko Commented Nov 21, 2024 at 10:03
2 Answers
Reset to default 1This 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
)
The outcome:
think you need to this function measureCellHeight()
can you check this code:
@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.chunked(2)) { rowItems ->
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
val rowHeights = rowItems.map { measureCellHeight(it) }
val maxHeight = rowHeights.maxOrNull() ?: 0.dp
rowItems.forEach { item ->
DynamicGridCell(
item = item,
maxHeight = maxHeight,
modifier = Modifier.weight(1f)
)
}
}
}
}
}
@Composable
private fun DynamicGridCell(item: Item, maxHeight: Dp, modifier: Modifier = Modifier) {
Card(
modifier = modifier
.fillMaxWidth()
.height(maxHeight)
) {
Column(
modifier = Modifier.fillMaxHeight()
) {
Box(
modifier = Modifier
.height(100.dp)
.fillMaxWidth()
.background(color = Color.Green),
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = item.title,
modifier = Modifier.padding(8.dp)
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = item.description,
modifier = Modifier
.padding(8.dp)
.fillMaxHeight()
)
}
}
}
@Composable
private fun measureCellHeight(item: Item): Dp {
var measuredHeight by remember { mutableStateOf(0.dp) }
Box(
modifier = Modifier.onGloballyPositioned { coordinates ->
measuredHeight = coordinates.size.height.toDp()
}
) {
DynamicGridCell(item = item, maxHeight = Dp.Infinity)
}
return measuredHeight
}
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742326410a4422840.html
评论列表(0条)