您可以定義 Grid 容器設定,建立可因應不同螢幕大小和內容類型的彈性版面配置。本頁面說明如何執行下列操作:
- 定義格線:設定資料列和資料欄的基本結構。
- 在格線中放置項目:瞭解項目在格線儲存格中的放置方式,以及如何變更流程方向。
- 管理軌道大小:使用固定、百分比、彈性和內建大小設定軌道大小。
- 設定間隙:管理列和欄之間的「溝槽」。
定義格線
格線由欄和列組成。
Grid 可組合函式具有 config 參數,可接受 lambda 來定義 GridConfigurationScope 中的欄和列。以下範例定義的格線有三列兩欄,每列/欄的大小都以 Dp 指定:
Grid( config = { repeat(2) { column(160.dp) } repeat(3) { row(90.dp) } } ) { }
在格線中放置項目
Grid 會擷取 content lambda 中的 UI 元素,並將其放入格線儲存格。無論您是否明確定義列和欄,格線都會排列項目。根據預設,Grid 會嘗試將 UI 元素放在資料列中可用的格線儲存格;如果無法,則會放在下一列中可用的格線儲存格。如果沒有空白儲存格,Grid 會建立新列。
在以下範例中,格線有六個格線儲存格,且每個儲存格都放置一張資訊卡 (圖 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 禁止查詢 SubcomposeLayout 的本質大小,這會支援 LazyColumn 和 LazyRow 等元件。
在標準彈性軌中放置 Lazy 清單會導致 IllegalStateException 損毀。如要在彈性格線軌道中安全地放置延遲清單,請使用 MinMax 和明確的最小大小 (例如 0.dp),略過內建的測量傳遞。
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() }