Jetpack Compose:构建带分隔符的自定义Column组件
自定义带动态分隔符的Column组件解决方案
你遇到的报错根源是Compose Layout系统的限制:每个Measurable对象只能被调用一次measure()方法,你的代码中循环多次调用同一个分隔符的measurable.measure(),直接触发了这个规则导致崩溃。
以下是修正后的实现方案,核心思路是只测量一次分隔符,复用其Placeable,同时精准筛选出实际渲染的子项:
@Composable fun ColumnWithChildrenSeparatedByDivider( modifier: Modifier = Modifier, divider: @Composable () -> Unit, content: @Composable () -> Unit, ) { Layout( modifier = modifier, contents = listOf(content, divider), ) { measurables, constraints -> // 测量所有内容子项,筛选出实际可见(宽高均大于0)的项 val visibleContentPlaceables = measurables.first() .map { it.measure(constraints) } .filter { it.width > 0 && it.height > 0 } // 仅在需要分隔符时(可见子项数>1)测量一次分隔符 val dividerPlaceable = if (visibleContentPlaceables.size > 1) { measurables[1].first().measure(constraints) } else { null } // 计算布局总尺寸:内容总高度 + 分隔符总高度 val totalHeight = visibleContentPlaceables.sumOf { it.height } + (dividerPlaceable?.height ?: 0) * (visibleContentPlaceables.size - 1) val totalWidth = constraints.maxWidth layout(totalWidth, totalHeight) { var currentY = 0 visibleContentPlaceables.forEachIndexed { index, placeable -> // 放置当前内容子项 placeable.place(x = 0, y = currentY) currentY += placeable.height // 非最后一个可见子项时,放置分隔符 if (index != visibleContentPlaceables.lastIndex && dividerPlaceable != null) { dividerPlaceable.place(x = 0, y = currentY) currentY += dividerPlaceable.height } } } } } @Composable fun Divider() { // 示例分隔符:灰色横线,占满宽度,高度1dp Box( modifier = Modifier .fillMaxWidth() .height(1.dp) .background(Color.Gray) ) }
关键修改说明
- 精准筛选可见子项:同时检查宽高是否大于0,确保只处理实际会渲染的内容
- 单次测量分隔符:仅在需要时测量一次分隔符的Placeable,复用它完成多次放置,避免重复测量报错
- 合理计算总高度:累加内容和分隔符的高度,保证布局尺寸符合实际需求
- 避免多余分隔符:通过
forEachIndexed判断是否为最后一个可见子项,不在末尾添加分隔符
内容的提问来源于stack exchange,提问作者Husayn Hakeem
相关产品推荐
相关产品推荐

