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 中,項目會以水平方式排列。horizontalArrangement FlowRow 中的參數可控制各項目之間的可用空間分配方式。

下表列出在項目上設定 horizontalArrangement 的範例 針對 FlowRow

已設定FlowRow的水平排列方式

結果

Arrangement.Start (Default)

使用 start 排序的項目

Arrangement.SpaceBetween

項目排列方式,中間有空格

Arrangement.Center

已置中排列的項目

Arrangement.End

結尾排列的項目

Arrangement.SpaceAround

排列項目時會保留空格

Arrangement.spacedBy(8.dp)

項目在特定 dp 的間距

FlowColumn 的類似選項可透過 verticalArrangement 使用,預設為 Arrangement.Top

交錯軸排列

交叉軸是與主軸相反方向的軸。例如,在 FlowRow 中,這是垂直軸。如要變更容器內部整體內容在交叉軸上的排列方式,請將 FlowRow 設為 verticalArrangement,將 FlowColumn 設為 horizontalArrangement

針對 FlowRow,下表列出在項目上設定不同 verticalArrangement 的範例:

FlowRow 上設定垂直排列方式

結果

Arrangement.Top (Default)

容器頂端排列

Arrangement.Bottom

容器底部排列

Arrangement.Center

容器中心排列方式

FlowColumnhorizontalArrangement 提供類似的選項。預設的橫向軸排列方式為 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

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

延遲載入流程項目

ContextualFlowRowContextualFlowColumnFlowRowFlowColumn 的專用版本,可讓您延後載入流程列或欄的內容。也提供項目位置的相關資訊 例如索引、列號和可用大小 列。這對大型資料集和您需要的情境資訊來說相當實用 關於某個項目的資訊

maxLines 參數會限制顯示的列數,而 overflow 參數則會指定在項目溢出時應顯示的內容,讓您指定自訂 expandIndicatorcollapseIndicator

舉例來說,如要顯示「+ (剩餘項目數量)」或「顯示較少項目」按鈕:

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

內容流程列的示例。
圖 2. ContextualFlowRow 的範例

商品重量

權重會根據因素和委刊項的可用空間而增加。 請注意,FlowRowRow 在使用權重來計算項目寬度的方式上有所差異。Rows 的重量 依據 Row 中的所有項目。在 FlowRow 中,權重會根據項目放置在哪個列中的項目,而非 FlowRow 容器中的所有項目。

舉例來說,如果有 4 個項目都落在同一行,且各自有不同的 1f, 2f, 1f3f 權重,則總權重為 7f。剩餘空間 資料列或資料欄中的值會除以 7f。接著,系統會使用 weight * (remainingSpace / totalWeight) 計算每個項目的寬度。

項目可以是 Modifier.weight 和最多項目,也可以搭配使用 FlowRowFlowColumn 可建立類似格線的版面配置。這種做法可用於建立可調整為裝置大小的回應式版面配置。

這裡有幾個使用權重可達成的目標。其中一個範例是項目大小相同的格狀檢視畫面,如下所示:

使用流動列建立的格狀檢視畫面
圖 3. 使用 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

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

您可以將權重與其他 Modifiers 結合,例如 Modifier.width(exactDpAmount), Modifier.aspectRatio(aspectRatio)Modifier.fillMaxWidth(fraction)。這些修飾符會依照 允許在 FlowRow (或 FlowColumn) 中調整項目大小。

您也可以建立不同大小的交替格線,其中有兩個項目 一個項目會佔據下一個寬度的一半 欄:

交替格狀與流動列
圖 5. 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

未設定寬度變更 (項目包裝)

未設定填滿上限欄寬