Jetpack Compose LazyVerticalGrid实现动态子项同高(不设固定高度)
解决LazyVerticalGrid每行网格项高度统一问题
我需要实现一个采用GridCells.Fixed(2)的LazyVerticalGrid,网格项会根据数据条件显示不同组件(比如数据不可用时隐藏对应组件)。要求每行的两个网格项高度一致,取该行中较高项的高度,且不想为网格项设置固定高度。
当前效果

预期效果(示例为设置固定高度后的效果)

基础实现代码
@Composable fun DynamicHeightGrid(items: List = listOf(item1, item2, item3, item4, item5)) { LazyVerticalGrid( columns = GridCells.Fixed(2), modifier = Modifier .padding(16.dp) ) { itemsIndexed(items) { index, item -> GridItem(item) } } } @Composable fun GridItem( content: RandomItems, ) { Card( modifier = Modifier .padding(4.dp) .fillMaxWidth() ) { Column( modifier = Modifier .padding(4.dp) ) { with(content) { Text(text = title!!, fontSize = 20.sp, maxLines = 3) Spacer(modifier = Modifier.height(2.dp)) Text(text = " Price: $price!!", fontSize = 24.sp) value?.let { Text(text = value, fontSize = 14.sp) } Text(text = shortDesc!!, fontSize = 14.sp) passion?.let { Text(text = passion, fontSize = 14.sp) } newValue?.let { Text(text = newValue, fontSize = 14.sp) } Spacer(modifier = Modifier.height(10.dp)) if (isRequired == true) { Button( onClick = { }, modifier = Modifier .height(20.dp) .fillMaxWidth() .background(Color.Red) ) { Text( color = Color.White, text = "Get New value" ) } } } } } }
已尝试的方案
- 调整LazyVerticalGrid网格项高度的相关方案
- Jetpack Compose中让Row内所有项高度一致的方案
解决方案:按行分组处理,使用Row实现高度同步
由于LazyVerticalGrid本身不支持自动对齐每行项的高度,我们可以将数据按行分组,用Row包裹每行的网格项,借助布局特性实现高度统一。
修改后的代码
@Composable fun DynamicHeightGrid(items: List<RandomItems> = listOf(item1, item2, item3, item4, item5)) { LazyColumn( modifier = Modifier .padding(16.dp) ) { // 将数据按每2个一组拆分,最后一组可能仅含1个元素 items.chunked(2).forEach { rowItems -> Row( modifier = Modifier .fillMaxWidth() .height(IntrinsicSize.Min), // 让Row高度适配该行最高的子项 horizontalArrangement = Arrangement.spacedBy(8.dp) ) { rowItems.forEach { item -> GridItem(item) .modifier .weight(1f) // 让两个网格项均分宽度 } // 最后一行只有1个元素时,添加占位符保持布局对称(可选) if (rowItems.size == 1) { Spacer(modifier = Modifier.weight(1f)) } } Spacer(modifier = Modifier.height(8.dp)) // 行之间的间距 } } } // 调整GridItem实现,移除fillMaxWidth(由weight控制宽度) @Composable fun GridItem( content: RandomItems, ): @Composable () -> Unit { return { Card( modifier = Modifier .padding(4.dp) ) { Column( modifier = Modifier .padding(4.dp) ) { with(content) { Text(text = title!!, fontSize = 20.sp, maxLines = 3) Spacer(modifier = Modifier.height(2.dp)) Text(text = " Price: $price!!", fontSize = 24.sp) value?.let { Text(text = value, fontSize = 14.sp) } Text(text = shortDesc!!, fontSize = 14.sp) passion?.let { Text(text = passion, fontSize = 14.sp) } newValue?.let { Text(text = newValue, fontSize = 14.sp) } Spacer(modifier = Modifier.height(10.dp)) if (isRequired == true) { Button( onClick = { }, modifier = Modifier .height(20.dp) .fillMaxWidth() .background(Color.Red) ) { Text( color = Color.White, text = "Get New value" ) } } } } } } }
方案说明
- 用
LazyColumn替代LazyVerticalGrid,将数据按每2个一组拆分,每行对应一个Row组件 Row设置height(IntrinsicSize.Min),让Row的高度自动适配该行中最高的子项- 每个网格项添加
Modifier.weight(1f),实现两个项的宽度均分 - 最后一行若只有1个元素,可添加占位符保持布局对称(根据需求选择是否保留)
这种方式无需设置固定高度,能自动让每行的两个网格项高度统一,完全符合需求。
内容的提问来源于stack exchange,提问作者Sudarshan Bhatt
相关产品推荐
相关产品推荐

