【问题标题】:Lazy Scrollable in Jetpack ComposeJetpack Compose 中的惰性可滚动
【发布时间】:2020-10-30 17:55:34
【问题描述】:

在 Jetpack Compose 中,Recycler 类型的视图称为 Lazy。

目前只有 Lazy Row 和 Lazy Column。

我有一个交错网格自定义 Composable,它是可滚动的。但是有没有办法让它变得懒惰?还是这样的 API 还不稳定?

【问题讨论】:

    标签: android android-jetpack-compose


    【解决方案1】:

    您可以通过多种方式实现相同的效果,其中一种是:

    @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
    }
    

    Owl sample app 中提取,不要忘记在ScrollableColumn 中包装/调用这个 Composable。

    编辑:随着compose 1.0.0-alpha09的发布,现在你有官方LazyVerticalGrid,请查看release notes

    【讨论】:

    • LazyVerticalGrid 不包含 StaggeredGrid 行为
    • 没问题,你仍然可以复制粘贴上面的代码sn-p,它有交错的效果,你也可以随意自定义
    • 是的,唯一的问题是,它不会是懒惰的
    • 你是对的,这两种解决方案都有一些警告。如果你想要完美的东西,你需要包装/自定义 LazyVerticalGrid 以实现交错效果
    【解决方案2】:

    如果您要实现自定义交错网格,我会说您实现的是交错行。然后创建另一个 Composable,它接收数据并在交错的行中提供数据,同时在内部为每一行使用一个惰性列。我不是要你实施新的东西。只需稍微调整现有的实现,这将大大提高性能。

    另外,如果你的数据不够大,可以不使用惰性容器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-15
      • 1970-01-01
      • 2021-05-26
      • 1970-01-01
      • 1970-01-01
      • 2023-01-07
      • 1970-01-01
      • 2022-10-23
      相关资源
      最近更新 更多