グリッド内の遅延リスト

4 つ星評価アイコン

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

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

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

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

ベスト プラクティス

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

材料

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

コンポーザブルで、lazyConfigGrid コンテナに渡します。content ラムダ内に静的コンポーネント(HeaderFooter)を配置し、Modifier.gridItem() とそれぞれのエリア ID を使用して位置を調整します。

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 を埋め込むことで、リスト項目を効率的に再利用し、実行時の例外を回避できるようになりました。

参考情報