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

如何修改LazyHorizontalStaggeredGrid的项目排列方向?能否指定行列位置?

实现LazyHorizontalStaggeredGrid的行优先排列(替代方案)

Jetpack Compose的LazyHorizontalStaggeredGrid默认采用列优先布局(先填满每列的垂直空间,再切换到下一列),目前官方没有提供直接切换为行优先(先填满每行的水平空间,再换行)的配置项。针对你高度相同、宽度不同的item列表需求,可根据item数量选择以下两种方案:

方案1:非懒加载场景(item数量少)

适合item数量不多的情况,用Compose原生Layout组件自定义行优先布局逻辑,搭配HorizontalScroll实现横向滚动。

自定义布局代码

@Composable
fun RowFirstHorizontalGrid(
    modifier: Modifier = Modifier,
    horizontalSpacing: Dp = 0.dp,
    verticalSpacing: Dp = 0.dp,
    content: @Composable () -> Unit
) {
    HorizontalScroll(modifier = modifier) {
        Layout(
            content = content,
            modifier = Modifier.wrapContentWidth()
        ) { measurables, constraints ->
            val horizontalSpacingPx = horizontalSpacing.roundToPx()
            val verticalSpacingPx = verticalSpacing.roundToPx()

            // 测量所有子项,强制高度与父容器一致
            val placeables = measurables.map { measurable ->
                measurable.measure(constraints.copy(minHeight = constraints.maxHeight, maxHeight = constraints.maxHeight))
            }

            // 按行分组:每行尽可能容纳更多item,超出父容器宽度则换行
            val rows = mutableListOf<List<Placeable>>()
            var currentRow = mutableListOf<Placeable>()
            var currentRowWidth = 0

            for (placeable in placeables) {
                val requiredWidth = placeable.width + if (currentRow.isNotEmpty()) horizontalSpacingPx else 0
                if (currentRow.isEmpty() || currentRowWidth + requiredWidth <= constraints.maxWidth) {
                    currentRow.add(placeable)
                    currentRowWidth += requiredWidth
                } else {
                    rows.add(currentRow)
                    currentRow = mutableListOf(placeable)
                    currentRowWidth = placeable.width
                }
            }
            if (currentRow.isNotEmpty()) rows.add(currentRow)

            // 计算整体布局的宽高
            val totalWidth = rows.maxOf { row ->
                row.sumOf { it.width } + (row.size - 1) * horizontalSpacingPx
            }
            val totalHeight = rows.sumOf { row -> row.maxOf { it.height } } + (rows.size - 1) * verticalSpacingPx

            // 摆放所有子项
            layout(totalWidth, totalHeight) {
                var yOffset = 0
                rows.forEach { row ->
                    var xOffset = 0
                    val rowHeight = row.maxOf { it.height }
                    row.forEach { placeable ->
                        // 垂直居中(因高度相同,也可直接使用yOffset)
                        placeable.placeRelative(x = xOffset, y = yOffset + (rowHeight - placeable.height) / 2)
                        xOffset += placeable.width + horizontalSpacingPx
                    }
                    yOffset += rowHeight + verticalSpacingPx
                }
            }
        }
    }
}

使用示例

// 模拟宽度不同的item数据集
val itemWidths = listOf(100, 80, 120, 90, 110, 70, 130)

RowFirstHorizontalGrid(
    modifier = Modifier.fillMaxHeight(0.5f), // 设置网格高度
    horizontalSpacing = 8.dp,
    verticalSpacing = 8.dp
) {
    itemWidths.forEach { width ->
        Box(
            modifier = Modifier.width(width.dp).background(Color.LightGray),
            contentAlignment = Alignment.Center
        ) {
            Text(text = "${width}dp")
        }
    }
}

方案2:懒加载场景(item数量多)

如果需要懒加载避免性能问题,官方组件暂时无法直接支持,需自定义LazyLayout的布局逻辑,这涉及实现LazyLayoutItemProvider、LayoutInfo等核心接口,复杂度较高。

简化替代思路:提前计算每行可容纳的item并分组,使用LazyColumn嵌套LazyRow实现垂直方向的懒加载,但此方案滚动方向为垂直,不符合横向滚动需求。若必须保留横向滚动,建议参考Compose Lazy布局源码扩展自定义懒加载行优先网格。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 18:53:12