Макет вспомогательной панели позволяет сосредоточить внимание пользователя на основном содержимом приложения, одновременно отображая соответствующую вспомогательную информацию. Например, на главной панели могут отображаться сведения о фильме, а на вспомогательной панели перечислены похожие фильмы, фильмы того же режиссера или произведения с участием тех же актеров.
Более подробную информацию см. в рекомендациях по вспомогательной панели Материала 3 .
Реализуйте вспомогательную панель с помощью NavigableSupportingPaneScaffold.
NavigableSupportingPaneScaffold
— это составной компонент, который упрощает реализацию вспомогательного макета панели в Jetpack Compose. Он оборачивает SupportingPaneScaffold
и добавляет встроенную навигацию и прогнозирующую обратную обработку.
Несущая панель поддерживает до трех стекол:
- Основная панель : отображает основной контент.
- Вспомогательная панель : предоставляет дополнительный контекст или инструменты, связанные с основной панелью.
- Дополнительная панель (необязательно) : используется для дополнительного содержимого, когда это необходимо.
Леса адаптируются в зависимости от размера окна:
- В больших окнах основная и вспомогательная панели отображаются рядом.
В маленьких окнах одновременно видна только одна панель, которая переключается по мере навигации пользователя.
Рисунок 1. Поддерживающая компоновка панели.
Добавить зависимости
NavigableSupportingPaneScaffold
— часть библиотеки адаптивных макетов Material 3 .
Добавьте следующие три связанные зависимости в файл build.gradle
вашего приложения или модуля:
Котлин
implementation("androidx.compose.material3.adaptive:adaptive") implementation("androidx.compose.material3.adaptive:adaptive-layout") implementation("androidx.compose.material3.adaptive:adaptive-navigation")
классный
implementation 'androidx.compose.material3.adaptive:adaptive' implementation 'androidx.compose.material3.adaptive:adaptive-layout' implementation 'androidx.compose.material3.adaptive:adaptive-navigation'
- адаптивный : низкоуровневые строительные блоки, такие как
HingeInfo
иPosture
- Adaptive-layout : адаптивные макеты, такие как
ListDetailPaneScaffold
иSupportingPaneScaffold
- Adaptive-navigation : Composables для навигации внутри и между панелями, а также адаптивные макеты, поддерживающие навигацию по умолчанию, такие как
NavigableListDetailPaneScaffold
иNavigableSupportingPaneScaffold
Убедитесь, что ваш проект включает Compose-material3-adaptive версии 1.1.0-beta1 или выше.
Включите интеллектуальный жест назад
Чтобы включить интеллектуальную анимацию назад в Android 15 или более ранней версии, вам необходимо включить поддержку прогнозируемого жеста назад. Чтобы принять участие, добавьте android:enableOnBackInvokedCallback="true"
в тег <application>
[или android:enableOnBackInvokedCallback="true"
в тег <application>
или отдельные теги <activity>
в файле AndroidManifest.xml
.
Если ваше приложение ориентировано на Android 16 (уровень API 36) или выше, функция прогнозирования включена по умолчанию.
Создать навигатор
В небольших окнах одновременно отображается только одна панель, поэтому используйте ThreePaneScaffoldNavigator
для перехода к панелям и обратно. Создайте экземпляр навигатора с помощью rememberSupportingPaneScaffoldNavigator
.
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope()
Передайте навигатор на эшафот
Для каркаса требуется ThreePaneScaffoldNavigator
, который представляет собой интерфейс, представляющий состояние каркаса, ThreePaneScaffoldValue
и PaneScaffoldDirective
.
NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { /*...*/ }, supportingPane = { /*...*/ }, )
Основная и вспомогательная панели представляют собой составные части, содержащие ваш контент. Используйте AnimatedPane
, чтобы применить анимацию панели по умолчанию во время навигации. Используйте значение scaffold, чтобы проверить, скрыта ли вспомогательная панель; если да, отобразите кнопку, которая вызывает 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() }, )
Если вам нужен больший контроль над конкретными аспектами каркаса, рассмотрите возможность использования 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() }, )