使用 ConstraintLayout 可以彻底干掉为了占位而存在的 Spacer 和嵌套的 Box,让布局层级变得非常扁平。
方案一:ConstraintLayout 写法(链式思维)
你需要先引入依赖:implementation("androidx.constraintlayout:constraintlayout-compose:1.0.1")
ConstraintLayout(
modifier = modifier
.fillMaxWidth()
.height(appDimens.dev.dp192)
.background(Color(0xFFE6E6E6))
.clickable(...)
.padding(horizontal = appDimens.dev.dp64)
) {
// 创建引用
val (contentRef, dividerRef) = createRefs()
// 1. 中间的内容 Row
Row(
modifier = Modifier
.fillMaxWidth()
.constrainAs(contentRef) {
top.linkTo(parent.top)
bottom.linkTo(parent.bottom) // 上下都连父布局,实现垂直居中
start.linkTo(parent.start)
end.linkTo(parent.end)
},
verticalAlignment = Alignment.CenterVertically
) {
Column(Modifier.weight(1f)) {
Text(text = title, ...)
if (showSubTitle && !subTitle.isNullOrEmpty()) {
Text(text = subTitle, ...)
}
}
Icon(painter = naviIcon, ...)
}
// 2. 底部的分割线
HorizontalDivider(
modifier = Modifier
.constrainAs(dividerRef) {
bottom.linkTo(parent.bottom) // 约束在父布局最底部
start.linkTo(parent.start)
end.linkTo(parent.end)
},
thickness = appDimens.dev.dp2,
color = Color(0x1A000000)
)
}
方案二:如果不想引入新库(更轻量化的写法)
模拟链式布局
如果你不想为了一个 Item 引入 ConstraintLayout 库,其实用原生的 Box 配合 align 也是一种"模拟链式布局"的策略:
Box(
modifier = modifier
.fillMaxWidth()
.height(appDimens.dev.dp192)
...
) {
// 居中的内容
Row(
modifier = Modifier
.fillMaxWidth()
.align(Alignment.Center) // 直接居中
.padding(horizontal = appDimens.dev.dp64),
verticalAlignment = Alignment.CenterVertically
) {
// ... Column + Icon
}
// 置底的分割线
HorizontalDivider(
modifier = Modifier.align(Alignment.BottomCenter), // 直接置底
...
)
}
为什么方案二往往更优?
- 性能:在 Compose 中,Box 的渲染开销比 ConstraintLayout 小。
- 简洁:不需要手动 createRefs()和编写复杂的 linkTo 约束。
- 结果一致:它实现了你想要的"Row 绝对居中,Divider 绝对置底"的效果,且没有 Spacer
占位。