您可以定义网格容器配置,以创建可根据不同屏幕尺寸和内容类型进行调整的灵活布局。 本页面介绍了如何执行以下操作:
- 定义网格:设置行和列的基本结构。
- 将项放置在网格中:了解如何将项放置到网格单元格中以及如何更改流向。
- 管理轨道尺寸:使用固定尺寸、百分比尺寸、灵活尺寸和固有尺寸来设置轨道尺寸。
- 设置间距:管理行与列之间的“边距”。
定义网格
网格由列和行组成。
Grid 可组合项具有 config 参数,该参数接受一个 lambda 来定义 GridConfigurationScope 中的列和行。
以下示例定义了一个包含三行两列的网格,每行和每列都具有在 Dp 中指定的固定大小:
Grid( config = { repeat(2) { column(160.dp) } repeat(3) { row(90.dp) } } ) { }
将内容放置在网格中
Grid 会获取 content lambda 中的界面元素,并将它们放置到网格单元中。无论您是否明确定义了行和列,网格都会布局列表项。
默认情况下,Grid 会尝试将界面元素放置在行中的可用网格单元格中;如果无法放置,则会将其放置在下一行中的可用网格单元格中。如果没有空单元格,Grid 会创建新行。
在以下示例中,网格有 6 个网格单元,每个单元都放置了一张卡片(图 1)。
每个网格单元的大小为 160dp x 90dp,因此网格总大小为 320dp x 270dp。
Grid( config = { repeat(2) { column(160.dp) } repeat(3) { row(90.dp) } } ) { Card1() Card2() Card3() Card4() Card5() Card6() }
如需将此默认行为更改为按列填充,请将 flow 属性设置为 GridFlow.Column。
Grid( config = { repeat(2) { column(160.dp) } repeat(3) { row(90.dp) } gap(8.dp) flow = GridFlow.Column // Grid tries to place items to fill the column }, ) { Card1() Card2() Card3() Card4() Card5() Card6() }
GridFlow.Row(左侧)和 GridFlow.Column(右侧)。
管理轨道尺寸
行和列统称为网格轨道。 您可以使用以下任一方法指定网格轨道的大小:
- 固定 (
Dp):分配特定大小(例如column(180.dp))。 - 百分比 (
Float):分配总可用空间中从0.0f到1.0f的百分比(例如,row(0.5f)表示 50%)。 - 灵活 (
Fr):在计算固定轨道和百分比轨道后,按比例分配剩余空间。例如,如果两行的值分别设置为1.fr和3.fr,则后者会获得剩余高度的 75%。 - 固有:根据轨道内的内容调整轨道大小。如需了解详情,请参阅内在确定网格轨道大小。
以下示例使用不同的轨道尺寸调整选项来定义行高:
Grid( config = { column(1f) row(100.dp) row(0.2f) row(1.fr) row(GridTrackSize.Auto) }, modifier = Modifier.height(480.dp) ) { PastelRedCard("Fixed(100.dp)") PastelGreenCard("Percentage(0.2f)") PastelBlueCard("Flex(1.fr)") PastelYellowCard("Auto") }
Grid 中的四种主要轨道尺寸调整选项定义的行高。
为灵活网格轨道设置最小尺寸
当网格容器没有剩余空间时,标准灵活轨道可以缩小到 0.dp。为防止这种情况并确保内容不会被压缩,请使用 GridTrackSize.MinMax 来强制设置明确的最小尺寸,同时保持轨道灵活性。
以下示例为第一行分配了至少 100.dp:
Grid( config = { column(1f) // The first row has a minimum height of 100.dp and can expand to // the half of the remaining space. row(GridTrackSize.MinMax(100.dp, 1.fr)) // The second row takes the half of the remaining space. row(1.fr) // The third row has a fixed height of 200.dp. row(200.dp) }, modifier = Modifier.size(360.dp) // Total grid height is 360.dp ) { PastelRedCard("MinMax(100.dp, 1.fr)") PastelGreenCard("Flex(1.fr)") PastelBlueCard("Fixed(200.dp)") }
100.dp。
设置放置延迟加载列表的网格轨道大小下限
标准灵活轨道会自动查询其子项的固有尺寸,以确定基本尺寸。不过,Jetpack Compose 禁止查询支持组件(例如 LazyColumn 和 LazyRow)的 SubcomposeLayout 的固有大小。
将延迟列表放置在标准灵活轨道中会导致 IllegalStateException 崩溃。
如需将延迟列表安全地放置在灵活的网格轨道内,请使用具有明确最小尺寸(例如 0.dp)的 MinMax 来绕过固有测量传递。
Grid( config = { column(1f) // The first row's height is determined by the height of the Text composable. row(GridTrackSize.Auto) // The second row occupies the remaining space, allowing the LazyColumn to scroll. row(GridTrackSize.MinMax(0.dp, 1.fr)) gap(8.dp) }, modifier = Modifier.size(width = 170.dp, height = 240.dp) ) { Text("Lazy column in a Grid") // The LazyColumn is placed in the second row, filling the remaining space. LazyColumn(verticalArrangement = Arrangement.spacedBy(4.dp)) { items(100) { number -> PastelGreenCard("Card $number") } } }
LazyColumn 在网格单元格中。
内在确定网格轨道大小
如果您希望布局适应内容,而不是强制将其放入固定容器中,则可以为 Grid 使用固有尺寸调整。网格轨道大小由以下值确定:
GridTrackSize.MaxContent:使用内容的最大固有大小(例如,宽度由不换行的文本块中文字的完整长度决定)。GridTrackSize.MinContent:使用内容的最小固有大小(例如,宽度由文本块中最长的单个字词决定)。GridTrackSize.Auto:使用可根据可用空间调整的灵活轨道尺寸。默认情况下,它的行为与MaxContent类似,但会缩小并包裹其内容以适应父容器。
以下示例将两段文字并排放置。 第一个文本的列大小由显示文本所需的最小宽度决定,而第二个列宽度取决于文本所需的最大宽度。
Grid( config = { column(GridTrackSize.MinContent) column(GridTrackSize.MaxContent) row(1.0f) }, modifier = Modifier.width(480.dp) ) { Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet.") Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet.") }
设置行和列之间的间距
网格轨道设置好大小后,您可以修改网格间距,以调整轨道之间的间距。
您可以使用 columnGap 函数指定列间距,并使用 rowGap 指定行间距。在以下示例中,每行之间有 16dp 的间距,每列之间有 8dp 的间距(图 5)。
Grid( config = { repeat(2) { column(160.dp) } repeat(3) { row(90.dp) } rowGap(16.dp) columnGap(8.dp) } ) { Card1() Card2() Card3() Card4() Card5() Card6() }
您还可以使用便捷函数 gap 来定义相同列大小和行大小的间距,以及使用单个函数分别定义列大小和间距大小。以下代码会向网格添加 8dp 间距:
Grid( config = { repeat(2) { column(160.dp) } repeat(3) { row(90.dp) } gap(8.dp) // Equivalent to columnGap(8.dp) and rowGap(8.dp) } ) { Card1() Card2() Card3() Card4() Card5() Card6() }