補助ペイン レイアウトを作成する

補助ペイン レイアウトでは、関連する補助情報を表示しながら、ユーザーの注意をアプリのメイン コンテンツに集中させることができます。たとえば、メインペインに映画の詳細が表示され、サポートペインに類似の映画、同じ監督の映画、同じ俳優が出演する作品が一覧表示されることがあります。

詳しくは、Material 3 のサポート ペインのガイドラインをご覧ください。

スキャフォールドを使用して補助ペインを実装する

NavigableSupportingPaneScaffold は、Jetpack Compose でサポート ペイン レイアウトの実装を簡素化するコンポーザブルです。SupportingPaneScaffold をラップし、組み込みのナビゲーションと予測型「戻る」の処理を追加します。

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

  • メインペイン: メイン コンテンツを表示します。
  • 補助ペイン: メインペインに関連する追加のコンテキストやツールを提供します。
  • 追加ペイン(省略可): 必要に応じて補足コンテンツを表示するために使用します。

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

  • 大きなウィンドウでは、メインペインと補助ペインが横に並んで表示されます。
  • 小さいウィンドウの場合、一度に 1 つのペインのみが表示され、ユーザーが移動すると切り替わります。

    メイン コンテンツがディスプレイの大部分を占め、補助コンテンツが横に表示されている。
    図 1. 補助ペイン レイアウト。

依存関係を追加する

NavigableSupportingPaneScaffoldマテリアル 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'
  • adaptive: 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)以降をターゲットにすると、予測型「戻る」はデフォルトで有効になります。

ナビゲーターを作成する

小さいウィンドウでは一度に 1 つのペインのみが表示されるため、ThreePaneScaffoldNavigator を使用してペイン間を移動します。rememberSupportingPaneScaffoldNavigator を使用してナビゲータのインスタンスを作成します。

val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator()
val scope = rememberCoroutineScope()

ナビゲータをスキャフォールドに渡す

スキャフォールドには、スキャフォールドの状態を表すインターフェースである ThreePaneScaffoldNavigatorThreePaneScaffoldValuePaneScaffoldDirective が必要です。

NavigableSupportingPaneScaffold(
    navigator = scaffoldNavigator,
    mainPane = { /*...*/ },
    supportingPane = { /*...*/ },
)

メインペインと補助ペインは、コンテンツを含むコンポーザブルです。AnimatedPane を使用して、ナビゲーション中にデフォルトのペイン アニメーションを適用します。スキャフォールディング値を使用して、サポート ペインが非表示になっているかどうかを確認します。非表示になっている場合は、navigateTo(SupportingPaneScaffoldRole.Supporting) を呼び出してサポート ペインを表示するボタンを表示します。

スキャフォールドの完全な実装は次のとおりです。

val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator()
val scope = rememberCoroutineScope()

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()) {
            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(
    modifier: Modifier = Modifier,
) {
    AnimatedPane(modifier = modifier.safeContentPadding()) {
        // Supporting pane content
        Text("This is the supporting pane")
    }
}

ペインをコンポーザブルに抽出すると、SupportingPaneScaffold の使用が簡素化されます(前のセクションの Scaffold の完全な実装と比較してください)。

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() },
)

スキャフォールドの特定の側面をより細かく制御する必要がある場合は、NavigableSupportingPaneScaffold ではなく SupportingPaneScaffold の使用を検討してください。PaneScaffoldDirectiveThreePaneScaffoldValue、または ThreePaneScaffoldState を個別に受け取ります。この柔軟性により、ペインの間隔のカスタム ロジックを実装し、同時に表示するペインの数を決定できます。ThreePaneScaffoldPredictiveBackHandler を追加して、予測型「戻る」のサポートを有効にすることもできます。

ThreePaneScaffoldPredictiveBackHandler を追加

スキャフォールド ナビゲータ インスタンスを受け取る予測型「戻る」ハンドラをアタッチし、backBehavior を指定します。これにより、戻るナビゲーション中にバックスタックからデスティネーションがポップされる方法が決まります。次に、scaffoldDirectivescaffoldStateSupportingPaneScaffold に渡します。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() },
)