リスト / 詳細は、デュアルペイン レイアウトで構成される UI パターンです。このレイアウトでは、1 つのペインにアイテムのリストが表示され、別のペインにはリストから選択されたアイテムの詳細が表示されます。
このパターンは、大規模なコレクションの要素に関する詳細情報を提供するアプリケーションに特に役立ちます。たとえば、メールのリストと各メール メッセージの詳細なコンテンツを持つメール クライアントなどです。リストと詳細は、重要度の低いパスにも使用できます。たとえば、アプリの設定をカテゴリのリストに分割し、各カテゴリの設定を詳細ペインに表示する場合などです。
ListDetailPaneScaffold
を使用して UI パターンを実装する
ListDetailPaneScaffold
は、アプリへのリスト / 詳細パターンの実装を簡素化するコンポーザブルです。リストと詳細のスキャフォールドは、リストペイン、詳細ペイン、オプションの追加ペインの最大 3 つのペインで構成されます。このスキャフォールドは、画面スペースの計算を処理します。十分な画面サイズがある場合は、リストペインの横に詳細ペインが表示されます。小さい画面サイズの場合、スキャフォールドは自動的にリストペインまたは詳細ペインを全画面表示します。
![リストページの横に表示される詳細ペイン。](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/list-detail-2.png?authuser=19&hl=ja)
![アイテムが選択されると、詳細ペインが画面全体に表示されます。](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/list-detail-1.png?authuser=19&hl=ja)
依存関係の宣言
ListDetailPaneScaffold
は、マテリアル 3 アダプティブ レイアウト ライブラリの一部です。
アプリには、次の 3 つの関連するマテリアル 3 ライブラリの依存関係を含める必要があります。
- adaptive -
HingeInfo
やPosture
などの下位レベルの構成要素 - adaptive-layout - アダプティブ レイアウト(
ListDetailPaneScaffold
、SupportingPaneScaffold
など)- adaptive-navigation - ペイン内およびペイン間を移動するためのコンポーザブル
アプリまたはモジュールの build.gradle
ファイルに依存関係を追加します。
Kotlin
implementation("androidx.compose.material3.adaptive:adaptive:1.0.0-alpha12") implementation("androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha12") implementation("androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha12")
Groovy
implementation 'androidx.compose.material3.adaptive:adaptive:1.0.0-alpha12' implementation 'androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha12' implementation 'androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha12'
基本的な使用方法
ListDetailPaneScaffold
を次のように実装します。
選択されるコンテンツを表すクラスを使用します。選択したリストアイテムの保存と復元をサポートするには、このクラスを
Parcelable
にする必要があります。kotlin-parcelize プラグインを使用してコードを生成します。@Parcelize class MyItem(val id: Int) : Parcelable
rememberListDetailPaneScaffoldNavigator
でThreePaneScaffoldNavigator
を作成し、BackHandler
を追加します。このナビゲータは、リストペイン、詳細ペイン、追加ペインの間を移動するために使用されます。汎用型を宣言すると、ナビゲータはスキャフォールドの状態(つまり、どのMyItem
が表示されているか)も追跡します。この型は Parcelable であるため、ナビゲータによって状態を保存および復元して、構成の変更を自動的に処理できます。BackHandler
は、システムの「戻る」ジェスチャーまたはボタンを使用した「戻る」をサポートします。ListDetailPaneScaffold
の [戻る] ボタンの想定される動作は、ウィンドウ サイズと現在のスキャフォールド値によって異なります。ListDetailPaneScaffold
が現在の状態に戻ることをサポートできる場合、canNavigateBack()
はtrue
になり、BackHandler
が有効になります。val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>() BackHandler(navigator.canNavigateBack()) { navigator.navigateBack() }
scaffoldState
をnavigator
からListDetailPaneScaffold
コンポーザブルに渡します。ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, // ... )
リストペインの実装を
ListDetailPaneScaffold
に提供する。ナビゲーション中にデフォルトのペイン アニメーションを適用するには、AnimatedPane
を使用します。次に、ThreePaneScaffoldNavigator
を使用して詳細ペインListDetailPaneScaffoldRole.Detail
に移動し、渡されたアイテムを表示します。ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = { AnimatedPane { MyList( onItemClick = { item -> // Navigate to the detail pane with the passed item navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item) } ) } }, // ... )
ListDetailPaneScaffold
に詳細ペインの実装を含めます。 ナビゲーションが完了すると、アプリが移動したペインがcurrentDestination
に含まれ、そのペインに表示されているコンテンツも含まれます。content
プロパティは元の remember 呼び出しで指定された型(この例ではMyItem
)と同じであるため、表示する必要があるデータのプロパティにもアクセスできます。ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = // ... detailPane = { AnimatedPane { navigator.currentDestination?.content?.let { MyDetails(it) } } }, )
上記の手順を実装すると、コードは次のようになります。
val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>() BackHandler(navigator.canNavigateBack()) { navigator.navigateBack() } ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = { AnimatedPane { MyList( onItemClick = { item -> // Navigate to the detail pane with the passed item navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item) }, ) } }, detailPane = { AnimatedPane { // Show the detail pane content if selected item is available navigator.currentDestination?.content?.let { MyDetails(it) } } }, )