如何使用 Jetpack compose 实现交错的网格布局?

Abh*_*Roy 11 android android-recyclerview android-jetpack-compose

据我所知,我们只能使用Rowsand ColumnsinJetpack Compose来显示列表。如何实现如下图所示的交错网格布局?使用 Recyclerview 和交错网格布局管理器的正常实现非常简单。但是如何在 中做同样的事情Jetpack Compose

交错网格布局

Une*_*nes 9

现在版本为 1.3.0-beta02。你可以这样实现:

LazyVerticalStaggeredGrid(
    columns = StaggeredGridCells.Fixed(2),
) {
    itemsIndexed((0..50).toList()) { i, item ->
        Box(
            Modifier
                .padding(2.dp)
                .fillMaxWidth()
                .height(20.dp * i)
                .background(Color.Cyan),
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

或者您可以使用水平视图LazyHorizontalStaggeredGrid


Sau*_*rat 8

Google 的 Compose 示例Owl 之一展示了如何进行交错网格布局。这是用于编写此代码的代码片段:

@Composable
fun StaggeredVerticalGrid(
    modifier: Modifier = Modifier,
    maxColumnWidth: Dp,
    children: @Composable () -> Unit
) {
    Layout(
        children = children,
        modifier = modifier
    ) { measurables, constraints ->
        check(constraints.hasBoundedWidth) {
            "Unbounded width not supported"
        }
        val columns = ceil(constraints.maxWidth / maxColumnWidth.toPx()).toInt()
        val columnWidth = constraints.maxWidth / columns
        val itemConstraints = constraints.copy(maxWidth = columnWidth)
        val colHeights = IntArray(columns) { 0 } // track each column's height
        val placeables = measurables.map { measurable ->
            val column = shortestColumn(colHeights)
            val placeable = measurable.measure(itemConstraints)
            colHeights[column] += placeable.height
            placeable
        }

        val height = colHeights.maxOrNull()?.coerceIn(constraints.minHeight, constraints.maxHeight)
                ?: constraints.minHeight
        layout(
                width = constraints.maxWidth,
                height = height
        ) {
            val colY = IntArray(columns) { 0 }
            placeables.forEach { placeable ->
                val column = shortestColumn(colY)
                placeable.place(
                        x = columnWidth * column,
                        y = colY[column]
                )
                colY[column] += placeable.height
            }
        }
    }
}

private fun shortestColumn(colHeights: IntArray): Int {
    var minHeight = Int.MAX_VALUE
    var column = 0
    colHeights.forEachIndexed { index, height ->
        if (height < minHeight) {
            minHeight = height
            column = index
        }
    }
    return column
}
Run Code Online (Sandbox Code Playgroud)

然后你可以传入你的可组合项目:

StaggeredVerticalGrid(
    maxColumnWidth = 220.dp,
    modifier = Modifier.padding(4.dp)
) {
    // Use your item composable here
}
Run Code Online (Sandbox Code Playgroud)

链接到示例中的代码段:https : //github.com/android/compose-samples/blob/1630f6b35ac9e25fb3cd3a64208d7c9afaaaedc5/Owl/app/src/main/java/com/example/owl/ui/courses/FeaturedCourses.kt#L161

  • 有谁知道如何使这个实现变得懒惰?对于数百件物品,它会变得很重 (2认同)