補助ペイン レイアウトを使用すると、関連する補助情報を表示しながら、アプリのメイン コンテンツにユーザーの注意を集中させることができます。たとえば、メインペインに映画の詳細を表示し、補助ペインに類似した映画、同じ監督の作品、同じ俳優が出演している作品を一覧表示できます。
詳しくは、マテリアル 3 の補助ペイン ガイドラインをご覧ください。
スキャフォールドを使用して補助ペインを実装する
NavigableSupportingPaneScaffold は、Jetpack Compose で補助ペイン レイアウトの実装を簡素化するコンポーザブルです。
SupportingPaneScaffold をラップし、組み込みのナビゲーションと予測型「戻る」の
処理を追加します。
補助ペイン スキャフォールドは、最大 3 つのペインをサポートします。
- メインペイン: プライマリ コンテンツを表示します。
- 補助ペイン: メインペインに関連する追加のコンテキストまたはツールを提供します。
- 追加ペイン(省略可): 必要に応じて補足コンテンツに使用します。
スキャフォールドはウィンドウ サイズに応じて調整されます。
- 大きなウィンドウでは、メインペインと補助ペインが横並びで表示されます。
**小さなウィンドウ**では、一度に 1 つのペインのみが表示され、ユーザーの操作に応じて切り替わります。
図 1.補助ペイン レイアウト。
依存関係を追加する
NavigableSupportingPaneScaffold は、マテリアル 3 のアダプティブ レイアウト
ライブラリの一部です。
次の 3 つの関連する依存関係をアプリまたはモジュールの build.gradle ファイルに追加します。
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'
adaptive-layout:
ListDetailPaneScaffoldやSupportingPaneScaffoldなどのアダプティブ レイアウトadaptive-navigation: ペイン内およびペイン間を移動するためのコンポーザブル。また、
NavigableListDetailPaneScaffoldやNavigableSupportingPaneScaffoldなど、デフォルトでナビゲーションをサポートするアダプティブ レイアウト
プロジェクトに compose-material3-adaptive バージョン 1.1.0-beta1 以降が含まれていることを確認します。
予測型「戻る」ジェスチャーをオプトインする
Android 15 以前で予測型「戻る」アニメーションを有効にするには、予測型「戻る」ジェスチャーのサポートをオプトインする必要があります。オプトインするには、
android:enableOnBackInvokedCallback="true" を <application> タグまたは
個々の <activity> タグに AndroidManifest.xml ファイル内に追加します。
アプリが Android 16(API レベル 36)以降をターゲットとする場合、予測型「戻る」はデフォルトで有効になります。
ナビゲータを作成する
小さなウィンドウでは一度に 1 つのペインしか表示されないため、
ThreePaneScaffoldNavigator を使用してペイン間を移動します。ナビゲータのインスタンスを
rememberSupportingPaneScaffoldNavigatorを使用して作成します。
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope()
ナビゲータをスキャフォールドに渡す
スキャフォールドには、スキャフォールドの状態を表すインターフェースである ThreePaneScaffoldNavigator、ThreePaneScaffoldValue、
PaneScaffoldDirective が必要です。
NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { /*...*/ }, supportingPane = { /*...*/ }, )
メインペインと補助ペインは、コンテンツを含むコンポーザブルです。
AnimatedPane を使用して、ナビゲーション中にデフォルトのペイン アニメーションを適用します。スキャフォールド値を使用して、補助ペインが非表示になっているかどうかを確認します。非表示になっている場合は、
navigateTo(SupportingPaneScaffoldRole.Supporting) を呼び出して
補助ペインを表示するボタンを表示します。
大きな画面の場合は、ThreePaneScaffoldNavigator.navigateBack()
メソッドを使用して補助ペインを閉じ、
BackNavigationBehavior.PopUntilScaffoldValueChange 定数を渡します。この
メソッドを呼び出すと、再コンポーズが強制的に実行されますNavigableSupportingPaneScaffold.
再コンポーズ中に、
ThreePaneScaffoldNavigator.currentDestination プロパティをチェックして
補助ペインを表示するかどうかを判断します。
スキャフォールドの完全な実装は次のとおりです。
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope() val backNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { AnimatedPane( modifier = Modifier .safeContentPadding() .background(Color.Red) ) { if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Hidden) { Button( modifier = Modifier .wrapContentSize(), onClick = { scope.launch { scaffoldNavigator.navigateTo(SupportingPaneScaffoldRole.Supporting) } } ) { Text("Show supporting pane") } } else { Text("Supporting pane is shown") } } }, supportingPane = { AnimatedPane(modifier = Modifier.safeContentPadding()) { Column { // Allow users to dismiss the supporting pane. Use back navigation to // hide an expanded supporting pane. if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Expanded) { // Material design principles promote the usage of a right-aligned // close (X) button. IconButton( modifier = Modifier.align(Alignment.End).padding(16.dp), onClick = { scope.launch { scaffoldNavigator.navigateBack(backNavigationBehavior) } } ) { Icon(Icons.Default.Close, contentDescription = "Close") } } Text("Supporting pane") } } } )
ペイン コンポーザブルを抽出する
SupportingPaneScaffold の個々のペインを独自のコンポーザブルに抽出して、再利用可能でテスト可能な状態にします。デフォルトのアニメーションが必要な場合は、ThreePaneScaffoldScope
を使用して AnimatedPane にアクセスします。
@OptIn(ExperimentalMaterial3AdaptiveApi::class) @Composable fun ThreePaneScaffoldPaneScope.MainPane( shouldShowSupportingPaneButton: Boolean, onNavigateToSupportingPane: () -> Unit, modifier: Modifier = Modifier, ) { AnimatedPane( modifier = modifier.safeContentPadding() ) { // Main pane content if (shouldShowSupportingPaneButton) { Button(onClick = onNavigateToSupportingPane) { Text("Show supporting pane") } } else { Text("Supporting pane is shown") } } } @OptIn(ExperimentalMaterial3AdaptiveApi::class) @Composable fun ThreePaneScaffoldPaneScope.SupportingPane( scaffoldNavigator: ThreePaneScaffoldNavigator<Any>, modifier: Modifier = Modifier, backNavigationBehavior: BackNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange, ) { val scope = rememberCoroutineScope() AnimatedPane(modifier = Modifier.safeContentPadding()) { Column { // Allow users to dismiss the supporting pane. Use back navigation to // hide an expanded supporting pane. if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Expanded) { // Material design principles promote the usage of a right-aligned // close (X) button. IconButton( modifier = modifier.align(Alignment.End).padding(16.dp), onClick = { scope.launch { scaffoldNavigator.navigateBack(backNavigationBehavior) } } ) { Icon(Icons.Default.Close, contentDescription = "Close") } } Text("Supporting pane") } } }
ペインをコンポーザブルに抽出すると、SupportingPaneScaffold の使用が簡単になります(次のコードと、前のセクションのスキャフォールドの完全な実装を比較してください)。
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope() NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { MainPane( shouldShowSupportingPaneButton = scaffoldNavigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden, onNavigateToSupportingPane = { scope.launch { scaffoldNavigator.navigateTo(ThreePaneScaffoldRole.Secondary) } } ) }, supportingPane = { SupportingPane(scaffoldNavigator = scaffoldNavigator) }, )
スキャフォールドの特定の側面をより細かく制御する必要がある場合は、
SupportingPaneScaffold ではなく NavigableSupportingPaneScaffold の使用を検討してください。これにより、PaneScaffoldDirective と ThreePaneScaffoldValue または
ThreePaneScaffoldState を個別に受け取ることができます。この柔軟性により、ペインの間隔のカスタム ロジックを実装し、同時に表示するペインの数を決定できます。ThreePaneScaffoldPredictiveBackHandler を追加して、予測型「戻る」のサポートを有効にすることもできます。
ThreePaneScaffoldPredictiveBackHandler を追加する
スキャフォールド ナビゲータ インスタンスを受け取る予測型「戻る」ハンドラをアタッチし、backBehavior を指定します。これにより、「戻る」ナビゲーション中にバックスタックから宛先をポップする方法が決まります。次に、scaffoldDirective と scaffoldState を SupportingPaneScaffold に渡します。ThreePaneScaffoldState を受け取るオーバーロードを使用し、scaffoldNavigator.scaffoldState を渡します。
SupportingPaneScaffold 内でメインペインと補助ペインを定義します。デフォルトのペイン アニメーションには AnimatedPane を使用します。
これらの手順を実装すると、コードは次のようになります。
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope() ThreePaneScaffoldPredictiveBackHandler( navigator = scaffoldNavigator, backBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange ) SupportingPaneScaffold( directive = scaffoldNavigator.scaffoldDirective, scaffoldState = scaffoldNavigator.scaffoldState, mainPane = { MainPane( shouldShowSupportingPaneButton = scaffoldNavigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden, onNavigateToSupportingPane = { scope.launch { scaffoldNavigator.navigateTo(ThreePaneScaffoldRole.Secondary) } } ) }, supportingPane = { SupportingPane(scaffoldNavigator = scaffoldNavigator) }, )