Макет вспомогательных панелей позволяет пользователю сосредоточиться на основном контенте приложения, одновременно отображая важную дополнительную информацию. Например, на главной панели может отображаться информация о фильме, а на вспомогательной — список похожих фильмов, фильмов того же режиссёра или работ с теми же актёрами.
Более подробную информацию см. в руководстве по вспомогательным панелям Material 3 .
Реализуйте опорную панель с помощью подмостей
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иPostureadaptive-layout : адаптивные макеты, такие как
ListDetailPaneScaffoldиSupportingPaneScaffoldadaptive-navigation : компонуемые элементы для навигации внутри панелей и между ними, а также адаптивные макеты, которые поддерживают навигацию по умолчанию, такие как
NavigableListDetailPaneScaffoldиNavigableSupportingPaneScaffold
Убедитесь, что ваш проект включает compose-material3-adaptive версии 1.1.0-beta1 или выше.
Включите функцию прогнозируемого жеста «назад»
Чтобы включить предиктивную анимацию «Назад» в Android 15 или более ранней версии, необходимо включить поддержку предиктивного жеста «Назад». Для этого добавьте 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) для отображения вспомогательной панели.
Для больших экранов используйте метод 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
Добавьте предиктивный обработчик обратных переходов, который принимает экземпляр навигатора Scaffold и указывает свойство 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) }, )