网格中的延迟列表

4 星级图标

Grid 可组合项可创建结构化的二维屏幕布局。 Grid 使用明确定义的轨道(行和列)和间隙作为界面的基础架构,定义了自适应布局结构。

由于 Grid 是结构化容器,而不是延迟加载容器,因此您需要明确定义放置在其中的每个元素,而无需在滚动时回收项。因此,直接在 Grid 中呈现大型或动态数据集可能会导致性能瓶颈,因为所有项会同时进行组合。

如需在结构化屏幕布局中显示大型数据集合,请在 Grid 单元格中嵌入延迟加载组件,例如 LazyColumn 或 LazyRow。 但请注意:灵活轨道(具有 1.fr 等规范)会查询子元素的固有尺寸。由于 SubcomposeLayout 不支持固有测量传递,因此将延迟列表放置在灵活轨道内会导致 IllegalStateException 崩溃。如需将延迟列表安全地放置在灵活的网格轨道内,您必须使用 GridTrackSize.MinMax 尺寸(例如 minmax(0.dp, 1.fr))来绕过固有测量传递。

屏幕布局:顶部有页眉,主要内容区域有可滚动的项目列表,底部有页脚。
图 1. 结构化屏幕布局,包含页眉、页脚和用于内容的嵌入式 LazyColumn。

最佳做法

  • 使用延迟列表,而不是大型显式循环:如需在结构化 Grid 中显示大型或动态数据集,请在特定网格单元中嵌入延迟组件(通常为 LazyColumn 或 LazyRow),而不是针对项创建大型显式循环,因为 Grid 不会回收项,并且有 1,000 个轨道的限制。
  • 为延迟列表使用 MinMax 轨道大小调整:由于 LazyColumn 和 LazyRow 不支持固有测量传递(请参阅 SubcomposeLayout),因此请在托管延迟组件的灵活轨道上使用 GridTrackSize.MinMax,以安全地绕过固有测量。

所需要素

  • Grid:可组合布局,用于将内容放置在通过显式行和列轨道配置的二维网格结构中。
  • LazyColumn:垂直滚动列表,仅组合和回收当前在屏幕上可见的项。
  • GridTrackSize.MinMax:轨道大小调整属性,用于定义灵活的边界(min 和 max),以安全地托管延迟加载组件,而不会触发运行时测量崩溃。
  • gridItem:Compose Modifier 扩展程序,用于将子界面元素分配给 Grid 内的特定单元格或命名区域。

步骤

通过定义语义区域标识符、使用 minmax 大小调整配置网格轨道以实现延迟列表兼容性,以及在网格内容区域内嵌入 LazyColumn,来构建屏幕布局。

1. 配置网格轨道和已命名的区域

创建一个 enum 类来表示屏幕布局的不同区域,并为布局轨道和命名区域定义 GridConfigurationScope lambda。对页眉和页脚行使用 GridTrackSize.MaxContent,以适应其内容尺寸;对托管延迟列表的内容轨道使用 minmax(0.dp, 1.fr),以便在不查询不受支持的固有测量值的情况下分配灵活空间:

enum class ScreenArea {
    Header,
    Content,
    Footer
}


val lazyConfig: GridConfigurationScope.() -> Unit = {
    column(minmax(0.dp, 1.fr))
    row(GridTrackSize.MaxContent)
    row(minmax(0.dp, 1.fr))
    row(GridTrackSize.MaxContent)

    area(ScreenArea.Header, row = 1, column = 1)
    area(ScreenArea.Content, row = 2, column = 1)
    area(ScreenArea.Footer, row = 3, column = 1)
    gap(8.dp)
}

2. 将静态组件放置在网格中

在可组合项中,将 lazyConfig 传递给 Grid 容器。在 content lambda 中,放置静态组件(Header 和 Footer),并使用 Modifier.gridItem() 及其各自的区域标识符来定位它们。

3. 在内容区域中嵌入 LazyColumn

在内容单元中,使用 Modifier.gridItem(ScreenArea.Content) 嵌入 LazyColumn。 由于内容轨道在第 1 步中配置了 minmax(0.dp, 1.fr),因此 LazyColumn 可以在滚动时安全地测量和回收项,而无需查询不受支持的固有尺寸:

@Composable
fun GridWithLazyColumn(
    modifier: Modifier = Modifier,
    items: List<String> = emptyList(),
) {
    Grid(
        modifier = modifier.fillMaxSize(),
        config = lazyConfig
    ) {
        Text("Header", Modifier.gridItem(ScreenArea.Header).padding(16.dp))
        Text("Footer", Modifier.gridItem(ScreenArea.Footer).padding(16.dp))

        // LazyColumn placed in the content area for large datasets
        LazyColumn(
            modifier = Modifier
                .gridItem(ScreenArea.Content)
                .fillMaxSize(),
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            items(items) { item ->
                Text(item, Modifier.padding(16.dp))
            }
        }
    }
}

结果

您的屏幕布局现在利用 Grid API 来定义整体二维页面结构,同时将 LazyColumn 嵌入到具有 minmax 大小的灵活轨道中,以高效回收列表项并避免运行时异常。

其他资源