グリッド内の遅延リスト

4 つ星評価のアイコン

Grid コンポーザブルは、構造化された 2 次元の画面レイアウトを作成します。Grid は、明示的に定義されたトラック(行と列)とギャップを UI の基本アーキテクチャとして使用して、レスポンシブ レイアウト構造を定義します。

Grid は遅延読み込みコンテナではなく構造コンテナであるため、スクロール時にアイテムをリサイクルせずに、配置するすべての要素を明示的に定義する必要があります。そのため、大規模なデータセットや動的なデータセットを Grid 内で直接レンダリングすると、すべてのアイテムが同時にコンポーズされるため、パフォーマンスのボトルネックが発生する可能性があります。

構造化された画面レイアウト内に大量のデータ コレクションを表示するには、LazyColumn や LazyRow などの遅延コンポーネントを Grid セルに埋め込みます。ただし、フレキシブル トラック(1.fr などの仕様)は、子要素の固有サイズをクエリします。SubcomposeLayout は、組み込み測定パスをサポートしていないため、フレキシブル トラック内に遅延リストを配置すると、IllegalStateException クラッシュが発生します。柔軟なグリッドトラック内に遅延リストを安全に配置するには、GridTrackSize.MinMax サイズ設定(minmax(0.dp, 1.fr) など)を使用して、固有の測定パスをバイパスする必要があります。

上部にヘッダー、メイン コンテンツ領域にスクロール可能なアイテムのリスト、下部にフッターがある画面レイアウト。
図 1. ヘッダー、フッター、コンテンツ用の埋め込み LazyColumn を含む構造的な画面レイアウト。

ベスト プラクティス

  • 大規模な明示的ループの代わりに遅延リストを使用する: 構造化された Grid 内に大規模なデータセットや動的なデータセットを表示するには、アイテムに対して大規模な明示的ループを作成するのではなく、特定のグリッドセル内に遅延コンポーネント(通常は LazyColumn または LazyRow)を埋め込みます。Grid はアイテムをリサイクルせず、トラック数の上限が 1,000 であるためです。
  • 遅延リストに MinMax トラックのサイズ設定を使用する: LazyColumn と LazyRow は固有の測定パスをサポートしていないため(SubcomposeLayout を参照)、遅延コンポーネントをホストするフレキシブル トラックで GridTrackSize.MinMax を使用して、固有の測定を安全にバイパスします。

材料

  • Grid: 明示的な行トラックと列トラックを使用して構成された 2 次元グリッド構造にアイテムを配置するコンポーザブル レイアウト。
  • LazyColumn: 画面に現在表示されているアイテムのみを構成して再利用する、垂直方向にスクロールするリスト。
  • GridTrackSize.MinMax: 柔軟な境界(min と max)を定義するトラックサイズ プロパティ。ランタイム測定のクラッシュをトリガーすることなく、遅延コンポーネントを安全にホストできます。
  • gridItem: 子 UI 要素を Grid 内の特定のセルまたは名前付き領域に割り当てる Compose Modifier 拡張機能。

手順

セマンティック領域識別子を定義し、遅延リストとの互換性を確保するために minmax サイズ設定でグリッドトラックを構成し、グリッド コンテンツ領域内に LazyColumn を埋め込むことで、画面レイアウトを構造化します。

1. グリッド トラックと名前付き領域を構成する

画面レイアウトの個別の領域を表す enum クラスを作成し、レイアウト トラックと名前付き領域の GridConfigurationScope ラムダを定義します。ヘッダー行とフッター行には GridTrackSize.MaxContent を使用して、コンテンツのサイズに合わせます。遅延リストをホストするコンテンツ トラックには minmax(0.dp, 1.fr) を使用して、サポートされていない固有の測定値をクエリすることなく、柔軟なスペースを割り当てます。

enum class ScreenArea {
    Header,
    Content,
    Footer
}


val lazyConfig: GridConfigurationScope.() -> Unit = {
    column(minmax(0.dp, 1.fr))
    row(GridTrackSize.MaxContent)
    row(minmax(0.dp, 1.fr))
    row(GridTrackSize.MaxContent)

    area(ScreenArea.Header, row = 1, column = 1)
    area(ScreenArea.Content, row = 2, column = 1)
    area(ScreenArea.Footer, row = 3, column = 1)
    gap(8.dp)
}

2. 静的コンポーネントを Grid に配置する

コンポーザブルで、lazyConfig を Grid コンテナに渡します。content ラムダ内に静的コンポーネント(Header と Footer)を配置し、Modifier.gridItem() を使用してそれぞれのエリア識別子で配置します。

3. コンテンツ領域に LazyColumn を埋め込む

コンテンツ セルで、Modifier.gridItem(ScreenArea.Content) を使用して LazyColumn を埋め込みます。コンテンツ トラックはステップ 1 で minmax(0.dp, 1.fr) を使用して構成されているため、LazyColumn は、サポートされていない固有のディメンションをクエリすることなく、スクロール時にアイテムを安全に測定してリサイクルできます。

@Composable
fun GridWithLazyColumn(
    modifier: Modifier = Modifier,
    items: List<String> = emptyList(),
) {
    Grid(
        modifier = modifier.fillMaxSize(),
        config = lazyConfig
    ) {
        Text("Header", Modifier.gridItem(ScreenArea.Header).padding(16.dp))
        Text("Footer", Modifier.gridItem(ScreenArea.Footer).padding(16.dp))

        // LazyColumn placed in the content area for large datasets
        LazyColumn(
            modifier = Modifier
                .gridItem(ScreenArea.Content)
                .fillMaxSize(),
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            items(items) { item ->
                Text(item, Modifier.padding(16.dp))
            }
        }
    }
}

結果

画面レイアウトでは、Grid API を使用して全体的な 2 次元ページ構造を定義し、minmax サイズ設定のフレキシブル トラックに LazyColumn を埋め込んで、リストアイテムを効率的にリサイクルし、ランタイム例外を回避しています。

参考情報