You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Jetpack Compose中为FlowRow设置maxLines行数限制?

可行方案:用SubcomposeLayout实现FlowRow两行截断

官方FlowRow没有暴露行数和测量细节,自定义完整Layout确实冗余,这里可以用SubcomposeLayout分阶段测量子组件,动态判断哪些标签能在两行内放下,最后添加省略指示器,完美适配不同场景的高度需求。

核心逻辑

  1. 先测量单个标签的高度,算出两行的总高度上限
  2. 逐个添加标签并实时计算整体高度,直到添加下一个标签会超出两行高度时停止
  3. 若存在溢出,添加省略指示器(如"...")

实现代码

@Composable
fun TwoLineFlowRow(
    modifier: Modifier = Modifier,
    horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
    verticalArrangement: Arrangement.Vertical = Arrangement.Top,
    items: List<String>,
    itemContent: @Composable (String) -> Unit,
    indicatorContent: @Composable () -> Unit
) {
    SubcomposeLayout(modifier = modifier) { constraints ->
        // 测量单个标签高度,确定两行最大允许高度
        val sampleItemPlaceable = subcompose("SampleItem") {
            itemContent(items.firstOrNull() ?: "")
        }.first().measure(constraints.copy(minWidth = 0))
        val singleItemHeight = sampleItemPlaceable.height
        val maxAllowedHeight = singleItemHeight * 2

        val placeables = mutableListOf<Placeable>()
        var currentRowWidth = 0
        var currentRowHeight = 0
        var totalHeight = 0
        var hasOverflow = false

        for (item in items) {
            val itemPlaceable = subcompose("Item-$item") { itemContent(item) }
                .first().measure(constraints.copy(minWidth = 0))

            // 判断当前标签加入后是否需要换行
            if (currentRowWidth + itemPlaceable.width > constraints.maxWidth) {
                // 换行后总高度是否超过两行
                if (totalHeight + currentRowHeight + itemPlaceable.height > maxAllowedHeight) {
                    hasOverflow = true
                    break
                }
                totalHeight += currentRowHeight
                currentRowWidth = itemPlaceable.width
                currentRowHeight = itemPlaceable.height
            } else {
                currentRowWidth += itemPlaceable.width
                currentRowHeight = max(currentRowHeight, itemPlaceable.height)
            }
            placeables.add(itemPlaceable)
        }

        // 处理省略指示器
        val indicatorPlaceable = if (hasOverflow) {
            subcompose("Indicator") { indicatorContent() }
                .first().measure(constraints.copy(minWidth = 0))
        } else null

        // 计算最终布局尺寸
        val finalWidth = constraints.maxWidth
        val finalHeight = min(totalHeight + currentRowHeight + (indicatorPlaceable?.height ?: 0), maxAllowedHeight)

        // 布局所有子组件
        layout(finalWidth, finalHeight) {
            var xPos = 0
            var yPos = 0
            var rowMaxHeight = 0

            placeables.forEach { placeable ->
                if (xPos + placeable.width > finalWidth) {
                    yPos += rowMaxHeight
                    xPos = 0
                    rowMaxHeight = 0
                }
                placeable.placeRelative(xPos, yPos)
                xPos += placeable.width
                rowMaxHeight = max(rowMaxHeight, placeable.height)
            }

            // 放置省略指示器
            indicatorPlaceable?.let {
                if (xPos + it.width > finalWidth) {
                    yPos += rowMaxHeight
                    xPos = 0
                }
                it.placeRelative(xPos, yPos)
            }
        }
    }
}

使用示例

TwoLineFlowRow(
    items = listOf("标签1", "标签2", "标签3", "标签4", "标签5", "标签6"),
    itemContent = { tag ->
        Text(
            text = tag,
            modifier = Modifier
                .padding(horizontal = 8.dp, vertical = 4.dp)
                .background(Color.Gray.copy(alpha = 0.2), RoundedCornerShape(16.dp))
                .padding(horizontal = 12.dp, vertical = 6.dp),
            fontSize = 14.sp
        )
    },
    indicatorContent = {
        Text(
            text = "...",
            modifier = Modifier
                .padding(horizontal = 8.dp, vertical = 4.dp)
                .background(Color.Gray.copy(alpha = 0.2), RoundedCornerShape(16.dp))
                .padding(horizontal = 12.dp, vertical = 6.dp),
            fontSize = 14.sp
        )
    }
)

注意事项

  • 代码会自动处理标签高度不一致的情况,每行高度取该行最高标签的高度,确保两行高度计算准确
  • 不需要硬编码高度,完全适配不同字体大小、标签样式的场景
  • 不依赖横向滚动,符合需求要求

内容的提问来源于stack exchange,提问作者Alejandra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:43:17