「リストと詳細」レイアウトを作成する

リストと詳細は、1 つのペインにアイテムのリストが表示され、別のペインにリストから選択したアイテムの詳細が表示される、デュアルペイン レイアウトで構成される UI パターンです。

このパターンは、メールのリストと各メール メッセージの詳細なコンテンツを含むメール クライアントなど、大規模なコレクションの要素に関する詳細情報を提供するアプリケーションに特に便利です。リスト詳細は、アプリの設定をカテゴリのリストに分割し、詳細ペインに各カテゴリの設定を表示するなど、重要性の低いパスにも使用できます。

リストページの横に表示される詳細ペイン。
図 1. 十分な画面サイズが使用可能な場合は、リストペインと並んで詳細ペインが表示されます。
アイテムを選択すると、詳細ペインが画面全体に表示されます。
図 2. 画面サイズが制限されている場合、アイテムが選択されているため、詳細ペインがスペース全体を占有します。

NavigableListDetailPaneScaffold を使用してリストと詳細のパターンを実装する

NavigableListDetailPaneScaffold は、Jetpack Compose でリスト詳細レイアウトの実装を簡素化するコンポーザブルです。ListDetailPaneScaffold をラップし、組み込みのナビゲーションと予測型「戻る」アニメーションを追加します。

リスト詳細スキャフォールドは、最大 3 つのペインをサポートします。

  1. リストペイン: アイテムのコレクションを表示します。
  2. 詳細ペイン: 選択したアイテムの詳細が表示されます。
  3. 追加ペイン(省略可: 必要に応じて追加のコンテキストを提供します。

スキャフォールドはウィンドウ サイズに基づいて適応します。

  • 大きなウィンドウでは、リストペインと詳細ペインが並んで表示されます。
  • 小さいウィンドウでは、一度に表示されるペインは 1 つだけです。ユーザーが移動すると切り替わります。

依存関係の宣言

NavigableListDetailPaneScaffoldマテリアル 3 アダプティブ ナビゲーション ライブラリの一部です。

アプリまたはモジュールの build.gradle ファイルに、次の 3 つの関連する依存関係を追加します。

Kotlin

implementation("androidx.compose.material3.adaptive:adaptive")
implementation("androidx.compose.material3.adaptive:adaptive-layout")
implementation("androidx.compose.material3.adaptive:adaptive-navigation")

Groovy

implementation 'androidx.compose.material3.adaptive:adaptive'
implementation 'androidx.compose.material3.adaptive:adaptive-layout'
implementation 'androidx.compose.material3.adaptive:adaptive-navigation'
  • 適応型: HingeInfoPosture などの低レベルの構成要素
  • adaptive-layout: ListDetailPaneScaffoldSupportingPaneScaffold などのアダプティブ レイアウト
  • adaptive-navigation: ペイン内やペイン間の移動用のコンポーザブル、および NavigableListDetailPaneScaffoldNavigableSupportingPaneScaffold など、デフォルトでナビゲーションをサポートするアダプティブ レイアウト

プロジェクトに compose-material3-adaptive バージョン 1.1.0-beta1 以降が含まれていることを確認します。

予測型「戻る」ジェスチャーをオプトインする

Android 15 以前で予測型「戻る」アニメーションを有効にするには、予測型「戻る」ジェスチャーをサポートするようにオプトインする必要があります。オプトインするには、AndroidManifest.xml ファイル内の <application> タグまたは個々の <activity> タグに android:enableOnBackInvokedCallback="true" を追加します。詳細については、予測型「戻る」ジェスチャーを有効にするをご覧ください。

アプリが Android 16(API レベル 36)以降をターゲットとしている場合、予測型「戻る」はデフォルトで有効になります。

基本的な使用方法

NavigableListDetailPaneScaffold を次のように実装します。

  1. 選択したコンテンツを表すクラスを使用します。選択したリストアイテムの保存と復元をサポートするには、Parcelable クラスを使用します。kotlin-parcelize プラグインを使用してコードを生成します。
  2. rememberListDetailPaneScaffoldNavigatorThreePaneScaffoldNavigator を作成します。

このナビゲータは、リストペイン、詳細ペイン、その他のペイン間を移動するために使用します。汎用型を宣言することで、ナビゲータはスキャフォールドの状態(表示されている MyItem)も追跡します。この型は Parcelable であるため、ナビゲータによって状態を保存して復元し、構成変更を自動的に処理できます。

  1. ナビゲータを NavigableListDetailPaneScaffold コンポーザブルに渡します。

  2. リストペインの実装を NavigableListDetailPaneScaffold に指定します。AnimatedPane を使用すると、ナビゲーション中にデフォルトのペイン アニメーションを適用できます。次に、ThreePaneScaffoldNavigator を使用して詳細ペイン ListDetailPaneScaffoldRole.Detail に移動し、渡されたアイテムを表示します。

  3. 詳細ペインの実装を NavigableListDetailPaneScaffold に含めます。

ナビゲーションが完了すると、currentDestination には、アプリが移動したペイン(ペインに表示されるコンテンツを含む)が含まれます。contentKey プロパティは元の呼び出しで指定された型と同じであるため、表示する必要があるデータにアクセスできます。

  1. 必要に応じて、NavigableListDetailPaneScaffolddefaultBackBehavior を変更します。デフォルトでは、NavigableListDetailPaneScaffolddefaultBackBehaviorPopUntilScaffoldValueChange を使用します。

アプリで別の「戻る」ナビゲーション パターンが必要な場合は、別の BackNavigationBehavior オプションを指定してこの動作をオーバーライドできます。

BackNavigationBehavior オプション

次のセクションでは、メールのリストが 1 つのペインに、詳細ビューが別のペインにあるメールアプリの例を使用します。

この動作は、全体的なレイアウト構造の変更に重点を置いています。マルチペイン設定では、詳細ペインでメール コンテンツを変更しても、基盤となるレイアウト構造は変更されません。そのため、現在のコンテキスト内で元に戻すレイアウト変更がないため、戻るボタンによってアプリまたは現在のナビゲーション グラフが終了することがあります。シングルペイン レイアウトでは、[戻る] を押すと、詳細ビュー内のコンテンツの変更をスキップしてリストビューに戻ります。これは、レイアウトの明確な変更を表します。

以下の例を考えてみましょう。

  • マルチペイン: 詳細ペインにメール(アイテム 1)が表示されています。別のメール(アイテム 2)をクリックすると、詳細ペインが更新されますが、リストペインと詳細ペインは引き続き表示されます。戻るボタンを押すと、アプリまたは現在のナビゲーション フローが終了する場合があります。
  • シングルペイン: アイテム 1 を表示してからアイテム 2 を表示し、[戻る] を押すと、メールリスト ペインに直接戻ります。

ユーザーが「戻る」アクションごとに異なるレイアウト遷移を認識できるようにする場合に使用します。

ナビゲーション値の変更。
PopUntilContentChange

この動作により、表示されるコンテンツの優先度が決まります。アイテム 1 を表示してからアイテム 2 を表示した場合、戻るボタンを押すと、レイアウトに関係なくアイテム 1 に戻ります。

以下の例を考えてみましょう。

  • マルチペイン: 詳細ペインで項目 1 を表示し、リストで項目 2 をクリックします。詳細ペインが更新されます。[戻る] を押すと、詳細ペインがアイテム 1 に戻ります。
  • シングルペイン: 同じコンテンツの復元が発生します。

ユーザーが「戻る」アクションで以前に表示したコンテンツに戻ることを想定している場合に使用します。

2 つの詳細ペイン間の遷移
PopUntilCurrentDestinationChange

この動作では、現在のナビゲーション デスティネーションが変更されるまでバックスタックがポップされます。これは、単一ペインとマルチペインの両方のレイアウトに適用されます。

以下の例を考えてみましょう。

シングルペイン レイアウトとマルチペイン レイアウトのどちらでも、[戻る] を押すと、ハイライト表示されたナビゲーション要素から前のデスティネーションにフォーカスが移動します。Gmail アプリでは、選択したペインの視覚的な表示が移動します。

現在のナビゲーションの明確な視覚的な表示を維持することがユーザー エクスペリエンスにとって重要である場合に使用します。

詳細ペインとリストペインの間を移動する
PopLatest

このオプションを選択すると、バックスタックから最新のデスティネーションのみが削除されます。中間状態をスキップせずに「戻る」ナビゲーションを行う場合は、このオプションを使用します。

これらの手順を実装すると、コードは次のようになります。

val scaffoldNavigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
val scope = rememberCoroutineScope()

NavigableListDetailPaneScaffold(
    navigator = scaffoldNavigator,
    listPane = {
        AnimatedPane {
            MyList(
                onItemClick = { item ->
                    // Navigate to the detail pane with the passed item
                    scope.launch {
                        scaffoldNavigator.navigateTo(
                            ListDetailPaneScaffoldRole.Detail,
                            item
                        )
                    }
                },
            )
        }
    },
    detailPane = {
        AnimatedPane {
            // Show the detail pane content if selected item is available
            scaffoldNavigator.currentDestination?.contentKey?.let {
                MyDetails(it)
            }
        }
    },
)