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

補助ペイン レイアウトでは、関連する補助情報を表示しながら、ユーザーのフォーカスをアプリのメイン コンテンツに維持します。たとえば、メインペインには映画の詳細が表示され、サブペインには類似の映画、同じ監督の映画、同じ俳優が出演する作品がリストされます。

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

NavigableSupportingPaneScaffold を使用して補助ペインを実装する

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

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

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

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

アプリが 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 の使用が簡単になります(以下を、前のセクションのスケルトンの完全な実装と比較してください)。

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