FlowRow
と FlowColumn
は、Row
や Column
に似たコンポーザブルですが、コンテナのスペースが不足するとアイテムが次の行に流れ込む点が異なります。これにより、複数の行または列が作成されます。1 行内のアイテム数は、maxItemsInEachRow
または maxItemsInEachColumn
を設定することで制御することもできます。多くの場合、FlowRow
と FlowColumn
を使用してレスポンシブ レイアウトを作成できます。アイテムが 1 つのディメンションに収まらない場合でも、コンテンツが切り捨てられることはありません。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
は、メイン軸で 1 行に表示できるアイテムの最大数を定義します。この数を超えると、次の行に折り返されます。デフォルトは 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
コンテナ内のすべてのアイテムではなく、アイテムが配置されている行内のアイテムに基づいています。
たとえば、1 行に 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) } }
重要な点は、別の項目を追加して 9 回ではなく 10 回繰り返すと、行全体の重みが 1f
になるため、最後の項目が最後の列全体を占有することです。
重みは、Modifier.width(exactDpAmount), Modifier.aspectRatio(aspectRatio)
や Modifier.fillMaxWidth(fraction)
などの他の Modifiers
と組み合わせることができます。これらの修飾子はすべて連携して動作し、FlowRow
(または FlowColumn
)内のアイテムのレスポンシブ サイズ設定を可能にします。
アイテムのサイズが異なるグリッドを交互に配置することもできます。2 つのアイテムがそれぞれ幅の半分を占め、1 つのアイテムが次の列の幅全体を占めるようにします。
これを実現するには、次のコードを使用します。
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)
を使用すると、アイテムが占有するコンテナのサイズを指定できます。これは、Row
または Column
に適用された場合の Modifier.fillMaxWidth(fraction)
の動作とは異なります。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()
FlowColumn
または FlowRow
内のアイテムに Modifier.fillMaxColumnWidth()
または Modifier.fillMaxRowHeight()
を適用すると、同じ列または行内のアイテムは、その列または行内の最大のアイテムと同じ幅または高さを占有します。
たとえば、この例では 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) ) } } }
各アイテムに適用される |
|
幅の変更が設定されていない(アイテムの折り返し) |
あなたへのおすすめ
- 注: JavaScript がオフになっている場合はリンクテキストが表示されます
- Compose レイアウトの基本
- Compose の ConstraintLayout
- エディタの操作 {:#editor-actions}