コンテナのプロパティを設定する

グリッド コンテナの構成を定義して、さまざまな画面サイズやコンテンツ タイプに対応する柔軟なレイアウトを作成できます。このページでは、次の操作を行う方法について説明します。

グリッドを定義する

グリッドは列と行で構成されます。コンポーザブル Grid には、GridConfigurationScope 内の列と行を定義するラムダを受け取る config パラメータがあります。次の例では、3 行 2 列のグリッドを定義しています。各行と列のサイズは Dp で指定されています。

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
    }
) {
}

アイテムをグリッドに配置する

Grid は、content ラムダ内の UI 要素を取得し、グリッドセルに配置します。グリッドは、行と列を明示的に定義したかどうかに関係なく、アイテムをレイアウトします。デフォルトでは、Grid は UI 要素を行の利用可能なグリッド セルに配置しようとします。配置できない場合は、次の行の利用可能なグリッド セルに配置します。空のセルがない場合、Grid は新しい行を作成します。

次の例では、グリッドに 6 つのグリッドセルがあり、それぞれにカードが配置されています(図 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()
}

3 行 2 列のグリッドに 6 枚のカードが配置されています。
図 1。3 行 2 列のグリッドに 6 つのカードが配置されています。

このデフォルトの動作を列単位の入力に変更するには、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()
}

フロー関数は、アイテムを配置する方向を変更します。
図 2GridFlow.Row(左)と GridFlow.Column(右)。

トラックのサイズ設定を管理する

行と列はまとめてグリッド トラックと呼ばれます。グリッド トラックのサイズは、次のいずれかの方法で指定できます。

  • 固定Dp): 特定のサイズ(column(180.dp) など)を割り当てます。
  • 割合Float): 0.0f から 1.0f までの使用可能な合計容量の割合を割り当てます(例: 50% の場合は row(0.5f))。
  • FlexibleFr): 固定トラックと割合トラックの計算後に、残りのスペースを比例配分します。たとえば、2 つの行が 1.fr3.fr に設定されている場合、後者は残りの高さの 75% を受け取ります。
  • Intrinsic: トラックのサイズを内部のコンテンツに基づいて設定します。詳細については、グリッド トラックのサイズを本質的に決定するをご覧ください。

次の例では、さまざまなトラック サイズ オプションを使用して行の高さを定義しています。

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

}

4 つのプライマリ トラック サイズ設定オプションを使用して定義された行の高さ。
図 3Grid の 4 つのプライマリ トラック サイズ設定オプションを使用して定義された行の高さ。

フレキシブル グリッド トラックの最小サイズを設定する

グリッド コンテナに空きスペースがない場合、標準のフレキシブル トラックは 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)")
}

4 つのプライマリ トラック サイズ設定オプションを使用して定義された行の高さ。
図 4。最初の行の高さは 100.dp 以上です。

遅延リストを配置するためのグリッド トラックの最小サイズを設定する

標準のフレキシブル トラックは、子の固有サイズを自動的にクエリして、ベースサイズを確立します。ただし、Jetpack Compose では、LazyColumnLazyRow などのコンポーネントをサポートする SubcomposeLayout の固有サイズをクエリすることは禁止されています。

標準のフレキシブル トラック内に遅延リストを配置すると、IllegalStateException クラッシュが発生します。レイジーリストをフレキシブル グリッド トラック内に安全に配置するには、明示的な最小サイズ(0.dp など)を指定した MinMax を使用して、固有の測定パスをバイパスします。

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

4 つのプライマリ トラック サイズ設定オプションを使用して定義された行の高さ。
図 5LazyColumn をグリッド セルに配置します。

グリッド トラック サイズを本質的に決定する

レイアウトを固定コンテナに強制的に配置するのではなく、コンテンツに合わせて調整したい場合は、Grid固有のサイズ設定を使用できます。グリッド トラックのサイズは次の値で決定されます。

  • GridTrackSize.MaxContent: コンテンツの最大固有サイズを使用します(例: 幅は、折り返しなしのテキスト ブロック内のテキストの全長によって決まります)。
  • GridTrackSize.MinContent: コンテンツの最小固有サイズを使用します(たとえば、幅はテキスト ブロック内の最長の単語によって決まります)。
  • GridTrackSize.Auto: 利用可能なスペースに基づいて調整されるトラックの柔軟なサイズを使用します。デフォルトでは MaxContent のように動作しますが、コンテンツを縮小して折り返し、親コンテナ内に収めます。

次の例では、2 つのテキストを横に並べて配置します。最初のテキストの列のサイズは、テキストを表示するために必要な最小幅によって決まります。2 番目の列の幅は、テキストに必要な最大幅によって決まります。

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

列で指定された固有サイズ。
図 5。列で指定された固有サイズ。

行と列の間の間隔を設定する

グリッド トラックのサイズを設定したら、グリッドギャップを変更して、トラック間の間隔を調整できます。列のギャップは 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()
}

行と列の間の間隔。
図 6。行と列の間のギャップ。

また、便利な関数 gap を使用して、同じ列と行のサイズのギャップを定義したり、1 つの関数を使用して列とギャップのサイズを個別に定義したりすることもできます。次のコードは、グリッドに 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()
}

名前付き領域でグリッド領域を定義する

名前付き領域を使用すると、グリッド セルのグループに名前を付けることができます。これはグリッド領域と呼ばれます。グリッドに UI 要素を配置するときに、座標インデックスの代わりにこれらの名前を使用できます。

名前付き領域を使用すると、コードの可読性が向上するという 2 つの主なメリットがあります。

  • グリッド レイアウトを定義する際に、想定されるコンテンツの目的と配置が明確になっている。
  • コンテンツを追加する際に、そのコンテンツの目的が明確である。

複雑なレイアウトを明確に整理するには、セマンティック グリッド領域を定義して、物理グリッド構造と子要素の配置を分離します。

config ラムダ内で、GridConfigurationScopearea 関数を使用して、グリッド内の名前付き領域を登録します。次に、対応する領域識別子を持つ gridItem 修飾子を使用して、これらの領域に子コンポーザブルを割り当てることができます。area 関数は、セマンティック識別子(enum クラス値や文字列キーなど)を物理グリッド座標のセットにマッピングします。グリッド線とインデックスは 1 ベースです(つまり、最初の行は 1、最初の列は 1 です)。

たとえば、4 つのエリア ID を持つグリッドを定義します。

/**
 * An enum representing the IDs for named areas within the grid.
 */
enum class GridAreaNames {
    Area1,
    Area2,
    Area3,
    Area4
}

areaId パラメータを使用して、領域の名前と、領域のセルの座標とスパンを指定します。次の例に示すように、gridItem 修飾子は areaId をキーとして使用し、各子アイテムを指定されたグリッド領域に割り当てます。

Grid(
    config = {
        // Define a single column that takes all available width.
        repeat(2) { column(0.5f) }

        // Define four rows, each taking 25% of the total height.
        repeat(4) { row(0.25f) }

        // Define named grid areas by associating an areaId with specific row and column indices.
        // Row and column indices are 1-based.
        area(areaId = GridAreaNames.Area1, row = 1, column = 1, columnSpan = 2)
        area(areaId = GridAreaNames.Area2, row = 2, column = 1, rowSpan = 3)
        area(areaId = GridAreaNames.Area3, rows = 2..3, columns = 2..2)
        area(areaId = GridAreaNames.Area4, row = 4, column = 2)

        gap(4.dp)
    },
    modifier = Modifier.size(360.dp)
) {
    PastelRedCard(
        "Area 1",
        // Use Modifier.gridItem(areaId) to place this composable into the
        // grid area defined with the matching ID in the config block.
        modifier = Modifier.gridItem(areaId = GridAreaNames.Area1)
    )
    PastelGreenCard(
        "Area 2",
        modifier = Modifier.gridItem(areaId = GridAreaNames.Area2)
    )
    PastelBlueCard(
        "Area 3",
        modifier = Modifier.gridItem(areaId = GridAreaNames.Area3)
    )
    PastelYellowCard(
        "Area 4",
        modifier = Modifier.gridItem(areaId = GridAreaNames.Area4)
    )
}

名前付き領域を使用すると、子コンポーザブルの順序やパラメータを変更することなく、config ラムダで物理レイアウト グリッド(行、列、トラック サイズの変更など)を再編成または調整できます。