admin管理员组文章数量:1332345
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
}
本文标签:
版权声明:本文标题:android - How to Align Items in a Vertical 2-Column Grid Row by the Tallest Item in Jetpack Compose? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742326410a2453815.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论