FlowRow
和 FlowColumn
是類似於 Row
和 Column
的可組合元件,但差別在於容器空間用盡時,項目會流入下一行。即可建立多個資料列或資料欄。您也可以設定 maxItemsInEachRow
或 maxItemsInEachColumn
,控制一行中的項目數量。您通常可以使用 FlowRow
和 FlowColumn
建構回應式版面配置,如果項目太大而無法放入單一維度,系統就不會截斷內容,而且將 maxItemsInEach*
與 Modifier.weight(weight)
搭配使用,有助於在需要時建構可填滿/展開資料列或欄寬度的版面配置。
常見的例子是用於方塊或篩選 UI:
基本用法
如要使用 FlowRow
或 FlowColumn
,請建立這些可組合項,並在其中放置應遵循標準流程的項目:
@Composable private fun FlowRowSimpleUsageExample() { FlowRow(modifier = Modifier.padding(8.dp)) { ChipItem("Price: High to Low") ChipItem("Avg rating: 4+") ChipItem("Free breakfast") ChipItem("Free cancellation") ChipItem("£50 pn") } }
這個程式碼片段會產生上述 UI,當第一列沒有空間時,項目會自動流到下一個列。
流程版面配置的功能
流程版面配置具有下列功能和屬性,可用於在應用程式中建立不同的版面配置。
主軸排列方式:水平或垂直排列
主軸是項目的排版軸,例如在 FlowRow
中,項目會以水平方式排列。FlowRow
中的 horizontalArrangement
參數會控管在項目之間分配可用空間的方式。
下表列出 FlowRow
在項目上設定 horizontalArrangement
的範例:
|
結果 |
|
|
FlowColumn
的類似選項可透過 verticalArrangement
使用,預設為 Arrangement.Top
。
交錯軸排列
交叉軸是與主軸相反的軸線。例如,在 FlowRow
中,這是垂直軸。如要變更容器內部整體內容在交叉軸上的排列方式,請將 FlowRow
設為 verticalArrangement
,將 FlowColumn
設為 horizontalArrangement
。
針對 FlowRow
,下表列出在項目上設定不同 verticalArrangement
的示例:
在 |
結果 |
|
|
FlowColumn
與 horizontalArrangement
提供類似的選項。預設的橫向軸排列方式為 Arrangement.Start
。
個別項目對齊
您可能會想在列中以不同對齊方式放置個別項目。這與 verticalArrangement
和 horizontalArrangement
不同,因為它會將項目對齊在目前的文字行內。您可以使用 Modifier.align()
套用此設定。
舉例來說,如果 FlowRow
中的項目高度不同,則該列會採用最大的項目高度,並將 Modifier.align(alignmentOption)
套用至項目:
在 |
結果 |
|
|
FlowColumn
也有類似的選項。預設對齊方式為 Alignment.Start
。
列或欄中的項目數量上限
參數 maxItemsInEachRow
或 maxItemsInEachColumn
會定義主軸中允許在單一行中顯示的項目上限,並在轉換至下一行的過程中保留這些項目。預設值為 Int.MAX_INT
,可讓盡可能多的項目,只要尺寸可放入該行即可。
舉例來說,設定 maxItemsInEachRow
會強制初始版面配置只包含 3 個項目:
未設定上限 |
|
延遲載入流程項目
ContextualFlowRow
和 ContextualFlowColumn
是 FlowRow
和 FlowColumn
的專屬版本,可讓您延後載入流程列或欄的內容。這些屬性也會提供項目位置 (索引、資料列編號和可用大小) 的相關資訊,例如項目是否位於第一列。這項功能適用於大型資料集,以及需要項目相關資訊的情況。
maxLines
參數會限制顯示的列數,而 overflow
參數則會指定在項目溢出時應顯示的內容,讓您指定自訂 expandIndicator
或 collapseIndicator
。
舉例來說,如要顯示「+ (剩餘項目數量)」或「顯示較少項目」按鈕:
val totalCount = 40 var maxLines by remember { mutableStateOf(2) } val moreOrCollapseIndicator = @Composable { scope: ContextualFlowRowOverflowScope -> val remainingItems = totalCount - scope.shownItemCount ChipItem(if (remainingItems == 0) "Less" else "+$remainingItems", onClick = { if (remainingItems == 0) { maxLines = 2 } else { maxLines += 5 } }) } ContextualFlowRow( modifier = Modifier .safeDrawingPadding() .fillMaxWidth(1f) .padding(16.dp) .wrapContentHeight(align = Alignment.Top) .verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.spacedBy(4.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), maxLines = maxLines, overflow = ContextualFlowRowOverflow.expandOrCollapseIndicator( minRowsToShowCollapse = 4, expandIndicator = moreOrCollapseIndicator, collapseIndicator = moreOrCollapseIndicator ), itemCount = totalCount ) { index -> ChipItem("Item $index") }
商品重量
權重會根據項目的因數和放置項目的線條可用空間,增加項目的權重。請注意,FlowRow
和 Row
在使用權重來計算項目寬度的方式上有所不同。對於 Rows
,權重會根據 Row
中的所有項目計算。在 FlowRow
中,權重會根據項目放置在哪個項目所在的列決定,而非 FlowRow
容器中的所有項目。
舉例來說,如果有 4 個項目都落在同一行,且各自有不同的 1f, 2f, 1f
和 3f
權重,則總權重為 7f
。列或欄中的剩餘空間會除以 7f
。接著,系統會使用 weight * (remainingSpace / totalWeight)
計算每個項目的寬度。
您可以將 Modifier.weight
和最大項目與 FlowRow
或 FlowColumn
結合,建立類似格狀的版面配置。這種做法可用於建立可調整為裝置大小的回應式版面配置。
以下列舉幾個使用權重可達成的效果。其中一個範例是項目大小相同的格狀檢視畫面,如下所示:
如要建立同樣項目大小的格線,您可以執行下列操作:
val rows = 3 val columns = 3 FlowRow( modifier = Modifier.padding(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), maxItemsInEachRow = rows ) { val itemModifier = Modifier .padding(4.dp) .height(80.dp) .weight(1f) .clip(RoundedCornerShape(8.dp)) .background(MaterialColors.Blue200) repeat(rows * columns) { Spacer(modifier = itemModifier) } }
請注意,如果您新增另一個項目並重複 10 次,而非 9 次,則最後一個項目會佔用整個最後一欄,因為整個資料列的總重量為 1f
:
您可以將權重與其他 Modifiers
結合,例如 Modifier.width(exactDpAmount), Modifier.aspectRatio(aspectRatio)
或 Modifier.fillMaxWidth(fraction)
。這些修飾符會一併運作,讓 FlowRow
(或 FlowColumn
) 中的項目可回應大小。
您也可以建立不同項目大小的格線交替畫面,其中兩個項目各佔一半寬度,一個項目則佔用下一個欄的整個寬度:
您可以使用下列程式碼完成這項操作:
FlowRow( modifier = Modifier.padding(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), maxItemsInEachRow = 2 ) { val itemModifier = Modifier .padding(4.dp) .height(80.dp) .clip(RoundedCornerShape(8.dp)) .background(Color.Blue) repeat(6) { item -> // if the item is the third item, don't use weight modifier, but rather fillMaxWidth if ((item + 1) % 3 == 0) { Spacer(modifier = itemModifier.fillMaxWidth()) } else { Spacer(modifier = itemModifier.weight(0.5f)) } } }
小數大小
您可以使用 Modifier.fillMaxWidth(fraction)
指定項目應佔用的容器大小。這與 Modifier.fillMaxWidth(fraction)
套用至 Row
或 Column
時的運作方式不同,因為 Row/Column
項目會占用剩餘寬度的百分比,而非整個容器的寬度。
舉例來說,以下程式碼在使用 FlowRow
和 Row
時會產生不同的結果:
FlowRow( modifier = Modifier.padding(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), maxItemsInEachRow = 3 ) { val itemModifier = Modifier .clip(RoundedCornerShape(8.dp)) Box( modifier = itemModifier .height(200.dp) .width(60.dp) .background(Color.Red) ) Box( modifier = itemModifier .height(200.dp) .fillMaxWidth(0.7f) .background(Color.Blue) ) Box( modifier = itemModifier .height(200.dp) .weight(1f) .background(Color.Magenta) ) }
|
|
|
fillMaxColumnWidth()
和fillMaxRowHeight()
將 Modifier.fillMaxColumnWidth()
或 Modifier.fillMaxRowHeight()
套用至 FlowColumn
或 FlowRow
中的項目,可確保同一欄或列中的項目占用與該欄/列中最大項目相同的寬度或高度。
舉例來說,這個範例會使用 FlowColumn
顯示 Android 甜點清單。您可以看到,當 Modifier.fillMaxColumnWidth()
套用至項目時,每個項目的寬度與未套用 Modifier.fillMaxColumnWidth()
且項目折行的寬度有何差異。
FlowColumn( Modifier .padding(20.dp) .fillMaxHeight() .fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp), maxItemsInEachColumn = 5, ) { repeat(listDesserts.size) { Box( Modifier .fillMaxColumnWidth() .border(1.dp, Color.DarkGray, RoundedCornerShape(8.dp)) .padding(8.dp) ) { Text( text = listDesserts[it], fontSize = 18.sp, modifier = Modifier.padding(3.dp) ) } } }
|
|
未設定寬度變更 (項目包裝) |
為您推薦
- 注意:系統會在 JavaScript 關閉時顯示連結文字
- Compose 版面配置的基本概念
- Compose 中的 ConstraintLayout
- 編輯器動作 {:#editor-actions}