Compose 中的流程版面配置

FlowRowFlowColumn 是類似於 RowColumn 的可組合函式,但不同之處在於,容器空間不足時,項目會流動到下一行。這樣會建立多個資料列或資料欄。您也可以設定 maxItemsInEachRowmaxItemsInEachColumn,控制一行中的項目數量。您通常可以使用 FlowRowFlowColumn 建構回應式版面配置,如果項目在某個維度過大,內容就不會遭到截斷。此外,搭配使用 maxItemsInEach*Modifier.weight(weight) 有助於建構版面配置,在需要時填滿/展開資料列或資料欄的寬度。

常見範例是晶片或篩選 UI:

FlowRow 中的 5 個晶片,顯示空間不足時溢位到下一行。
圖 1.FlowRow
」的範例

基本用法

如要使用 FlowRowFlowColumn,請建立這些可組合項,並將應遵循標準流程的項目放在其中:

@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 的範例:

水平排列設定為「FlowRow

結果

Arrangement.Start (Default)

以開始時間排序的項目

Arrangement.SpaceBetween

項目排列方式 (項目之間有間距)

Arrangement.Center

項目排列在中央

Arrangement.End

項目排列在結尾

Arrangement.SpaceAround

項目周圍有間距

Arrangement.spacedBy(8.dp)

項目間隔特定 dp

如為 FlowColumnverticalArrangement 提供類似選項,預設為 Arrangement.Top

交錯軸排列方式

交叉軸是與主軸方向相反的軸。舉例來說,在 FlowRow 中,這是垂直軸。如要變更容器內整體內容在交叉軸的排列方式,請對 FlowRow 使用 verticalArrangement,對 FlowColumn 使用 horizontalArrangement

如要設定 FlowRow,請參閱下表,瞭解如何為項目設定不同的 verticalArrangement

FlowRow 上設定垂直排列方式

結果

Arrangement.Top (Default)

容器頂部排列方式

Arrangement.Bottom

容器底部排列方式

Arrangement.Center

容器中心排列方式

如要使用 FlowColumn,可以透過 horizontalArrangement 取得類似選項。 預設的交叉軸排列方式為 Arrangement.Start

個別項目對齊

您可能想以不同對齊方式,在列中放置個別項目。這與 verticalArrangementhorizontalArrangement 不同,因為它會對齊目前行內的項目。你可以使用 Modifier.align()套用這項設定。

舉例來說,如果 FlowRow 中的項目高度不同,系統會以最高項目的高度為準,並對項目套用 Modifier.align(alignmentOption)

FlowRow 上設定垂直對齊

結果

Alignment.Top (Default)

所有項目靠上對齊

Alignment.Bottom

所有項目靠下對齊

Alignment.CenterVertically

所有項目置中對齊

FlowColumn 也有類似選項。預設對齊方式為 Alignment.Start

資料列或資料欄中的項目數量上限

參數 maxItemsInEachRowmaxItemsInEachColumn 會定義主軸中允許在一行顯示的最大項目數,超過這個數量就會換行。預設值為 Int.MAX_INT,只要項目大小允許,即可盡可能容納更多項目。

舉例來說,設定 maxItemsInEachRow 會強制初始版面配置只包含 3 個項目:

未設定上限

maxItemsInEachRow = 3

流程列未設定上限 流程列設定的項目數量上限

商品重量

項目會根據其係數和放置所在行的可用空間增加權重。請注意,FlowRowRow 在權重的使用方式上有所不同,因此計算項目寬度的方式也不一樣。如果是 Rows,重量是根據 Row 中的所有項目計算。使用 FlowRow 時,權重會根據項目所在行中的項目計算,而不是 FlowRow 容器中的所有項目。

舉例來說,假設您有 4 個項目都位於同一行,且權重分別為 1f, 2f, 1f3f,則總權重為 7f。系統會將列或欄中的剩餘空間除以 7f。接著,系統會使用 weight * (remainingSpace / totalWeight) 計算每個項目的寬度。

您可以搭配使用 Modifier.weightFlowRowFlowColumn 的最大項目數,建立類似格線的版面配置。這種方法有助於建立自動調整式版面配置,配合裝置大小調整。

權重可達成多種目標,以下列舉幾個範例。其中一個例子是項目大小相同的格線,如下所示:

以流程列建立的格線
圖 2. 使用 FlowRow 建立格線

如要建立大小相同的項目格線,請按照下列步驟操作:

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

格狀檢視畫面中的最後一個項目會顯示完整大小
圖 3. 使用 FlowRow 建立格線,讓最後一個項目佔用完整寬度

您可以將權重與其他 Modifiers 結合,例如 Modifier.width(exactDpAmount), Modifier.aspectRatio(aspectRatio)Modifier.fillMaxWidth(fraction)。這些修飾符會共同運作,讓 FlowRow (或 FlowColumn) 內的項目大小可因應變化。

您也可以建立不同項目大小的交替格線,其中兩個項目各佔一半寬度,一個項目則佔下一個資料欄的完整寬度:

交替格線與流程列
圖 4. FlowRow,列大小交替

您可以使用下列程式碼達成這個目標:

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),您可以指定項目應佔用的容器大小。這與套用至 RowColumn 時的 Modifier.fillMaxWidth(fraction) 運作方式不同,因為 Row/Column 項目會佔用剩餘寬度的百分比,而不是整個容器的寬度。

舉例來說,下列程式碼使用 FlowRowRow 時會產生不同結果:

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

FlowRow:中間項目,占整個容器寬度的 0.7 分數。

具有流程列的分數寬度

Row:中間項目佔剩餘 Row 寬度的 0.7%。

列的分數寬度

fillMaxColumnWidth()fillMaxRowHeight()

Modifier.fillMaxColumnWidth()Modifier.fillMaxRowHeight() 套用至 FlowColumnFlowRow 內的項目,可確保同一欄或同一列中的項目寬度或高度,與該欄/列中最大的項目相同。

舉例來說,這個範例會使用 FlowColumn 顯示 Android 甜點清單。您可以查看將 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)
            )
        }
    }
}

Modifier.fillMaxColumnWidth()已套用至每個項目

fillMaxColumnWidth

未設定寬度變更 (項目換行)

未設定填滿最大欄寬