请教个 Jetpack Compose 的布局问题

186 天前
 magic3584

我想做一个类似物流的一个页面类似下图,但是左边那条绿线无法显示出来。(代码和图片在后面)

  1. Row(modifier = Modifier.height(IntrinsicSize.Min)) 并且把图片 grid 注释掉,那么绿线是正常显示的
  2. Row(modifier = Modifier.fillMaxHeight)并且设置 grid 的 height ,也无法显示
@Composable
fun ListDemo() {
    var titles = listOf("1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2")
    LazyColumn(modifier = Modifier
        .fillMaxSize()) {
        itemsIndexed(titles) { index, item ->
            Surface(modifier = Modifier
                .fillMaxWidth()) {
                Column(modifier = Modifier
                    .padding(horizontal = 18.dp)) {
                    Row(modifier = Modifier
                        .padding(vertical = 8.dp),
                        verticalAlignment = Alignment.CenterVertically) {
                        Box(modifier = Modifier
                            .size(24.dp)
                            .background(Color.Red))
                    }

                    Row(modifier = Modifier
                        .fillMaxWidth()) {
                        Box(modifier = Modifier
                            .width(24.dp)
                            .fillMaxHeight(IntrinsicSize.Min),
                            contentAlignment = Alignment.Center){
                            // TODO show this green line
                            Box(modifier = Modifier
                                .fillMaxHeight()
                                .width(1.dp)
                                .background(Color.Green))
                        }
                        Spacer(Modifier.width(8.dp))
                        Column(modifier = Modifier
                            .fillMaxWidth(),
                            verticalArrangement = Arrangement.spacedBy(8.dp)) {
                            Row(modifier = Modifier
                                .fillMaxWidth()) {
                                Text(
                                    text = "Time:",
                                    fontSize = 14.sp,
                                    color = Color.Gray,
                                    modifier = Modifier
                                        .width(100.dp)
                                )
                                Spacer(Modifier.width(4.dp))
                                Text(
                                    text = "2023-03-02 18:34:07",
                                    fontSize = 14.sp,
                                    color = Color.Gray
                                )
                            }

                            val images = listOf("1","2","3","4")
                            LazyVerticalGrid(
                                columns = GridCells.Fixed(3),
                                horizontalArrangement = Arrangement.spacedBy(6.dp),
                                verticalArrangement = Arrangement.spacedBy(6.dp),
                                modifier = Modifier.heightIn(
                                    max = 1000.dp)
                            ) {
                                items(images) { pic ->
                                    Box(
                                        modifier = Modifier
                                            .aspectRatio(1f)
                                            .background(Color.Gray)
                                    ) {
                                        Text(
                                            text = pic
                                        )
                                    }
                                }
                            }

                        }
                    }

                    Spacer(Modifier.height(8.dp))
                }


            }
        }
    }
}

@Preview
@Composable
fun ListDemoPreview() {
    ListDemo()
}
2859 次点击
所在节点    Android
18 条回复
vigroid
186 天前
Column( weight = 1f ) , 不要加上 fillMaxWidth()。占据剩余的空间应该用 weight = 1f
magic3584
186 天前
@vigroid
不行,右侧 Column 用 weight(1) 或者 fillMaxWidth() 这里是同样的效果
qwell
186 天前
Row(modifier = Modifier.height(IntrinsicSize.Min)) {
Box(modifier = Modifier
.width(24.dp)
.fillMaxHeight(),
contentAlignment = Alignment.Center){
Box(modifier = Modifier
.fillMaxHeight()
.width(1.dp)
.background(Color.Green))
}
Spacer(Modifier.width(8.dp))
Column(modifier = Modifier
.weight(1f),
verticalArrangement = Arrangement.spacedBy(8.dp)) {...}
}
这样,有一点是两个 LazyLayout 滑动冲突了
magic3584
186 天前
@qwell #3
不行,还是会报错
```shell
java. lang. IllegalStateException: Asking for intrinsic measurements of SubcomposeLayout layouts is not supported. This includes components that are built on top of SubcomposeLayout, such as lazy lists, BoxWithConstraints, TabRow, etc. To mitigate this: - if intrinsic measurements are used to achieve 'match parent' sizing, consider replacing the parent of the component with a custom layout which controls the order in which children are measured, making intrinsic measurement not needed - adding a size modifier to the component, in order to fast return the queried intrinsic measurement.
```
jojo0830
186 天前
动态获取 Column 的高度吧。
Column(
modifier = Modifier
.fillMaxWidth()
.onSizeChanged {
sizeInDp = with(density) {
it.width.toDp() to it.height.toDp()
}
},
verticalArrangement = Arrangement.spacedBy(8.dp)
),
然后把高度给到 box 。
Box(
modifier = Modifier
.width(24.dp)
.height(sizeInDp.second)
.background(Color.Red),
contentAlignment = Alignment.Center
)
jojo0830
186 天前
@jojo0830 但是你这样绿色也没跟红色方块接触,不好看,重新调整布局吧
qwell
186 天前
@magic3584 因为你嵌套了两个 lazylayout ,你把里面的 lazyverticalgrid 设个固定高度
od66666666
186 天前
遇 size 不决,直接 onGloballyPositioned

Row(modifier = Modifier.fillMaxWidth()) {
val density = LocalDensity.current
var columnHeight by remember { mutableStateOf(0.dp) }
Box(
modifier = Modifier
.height(columnHeight)
.width(24.dp),
contentAlignment = Alignment.Center
) {
...
}
Spacer(Modifier.width(8.dp))
Column(modifier = Modifier
.onGloballyPositioned { layoutCoordinates ->
columnHeight =
with(density) { layoutCoordinates.size.height.toDp() }
}
.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(8.dp)) {
...
}
}
lisongeee
186 天前
上面报错已经说得很明白了,你的子布局有无法确定 size 的组件 LazyVerticalGrid

LazyXXX 就是前端概念里的虚拟列表,必须要一个容器高度才能计算虚拟滚动

或者换成自定义 Column{Row{}}
zeropercenthappy
186 天前
从你的布局来看,内部的列表应该没有必要使用 LazyVerticalGrid ,这里应该是 Lazy 控件导致的高度计算问题。考虑直接换成 FlowRow 吧。
leiiiooo
186 天前
使用 Canvas 自定义吧,我也试了半天😂
lisongeee
186 天前
https://gist.github.com/lisonge/b689ea150c7df8ae2618c4f73203ad9e

整了半天,发现在外面套个 box 就行,代码和运行截图都在上面的 gist 里了
magic3584
186 天前
@jojo0830 #5
您这个 density 从哪来的?
import androidx.compose.ui.draw.EmptyBuildDrawCacheParams.density
一直报错,`Cannot access 'EmptyBuildDrawCacheParams': it is private in file`
magic3584
186 天前
@qwell #7
图片是宽高比 1:1 ,想让它自动去布局。如果设置固定高度的话需要去计算
jojo0830
186 天前
@magic3584 #13
顶层创建一个呗:
val density = LocalDensity.current
var sizeInDp by remember { mutableStateOf(0.dp to 0.dp) }
magic3584
186 天前
@jojo0830 #5
感谢,可以了。请忽略 13 楼回复
magic3584
186 天前
@od66666666 #8
感谢,您这个跟 5 楼的差不多
magic3584
186 天前
@lisongeee #12
您的布局方式跟我的不太一样,我学一下

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1118203

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX