Создание вспомогательного макета панели

Канонический макет вспомогательной панели фокусирует внимание пользователя на основном содержимом вашего приложения, а также отображает соответствующий вспомогательный контент. Например, на основной панели содержимого может отображаться информация о недавно вышедшем фильме, а на вспомогательной панели отображается список других фильмов, имеющих аналогичную тему или того же режиссера или актеров в главных ролях. Дополнительные сведения о каноническом макете вспомогательной панели см. в рекомендациях по вспомогательной панели Материала 3 .

Реализация вспомогательной панели

SupportingPaneScaffold состоит из трех панелей: основной панели, вспомогательной панели и дополнительной панели. Подсистема выполняет все расчеты по распределению оконного пространства между тремя панелями. На больших экранах в scaffold отображается основная панель, а вспомогательная панель находится сбоку. На маленьких экранах scaffold отображает либо основную, либо вспомогательную панель в полноэкранном режиме.

Основной контент занимает большую часть экрана, рядом с ним находится вспомогательный контент.
Рис. 1. Поддерживающая компоновка панели.

Добавить зависимости

SupportingPaneScaffold — часть библиотеки адаптивных макетов 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 — Адаптивные макеты, такие как SupportingPaneScaffold
  • Adaptive-navigation — Составные элементы для навигации внутри и между панелями

Создайте навигатор и эшафот

В небольших окнах одновременно отображается только одна панель, поэтому используйте ThreePaneScaffoldNavigator для перехода к панелям и обратно. Создайте экземпляр навигатора с помощью rememberSupportingPaneScaffoldNavigator . Для обработки жестов возврата используйте BackHandler , который проверяет canNavigateBack() и вызывает navigateBack() :

val navigator = rememberSupportingPaneScaffoldNavigator()

BackHandler(navigator.canNavigateBack()) {
    navigator.navigateBack()
}

Для scaffold требуется PaneScaffoldDirective , который определяет, как разделить экран и сколько пространства использовать, и ThreePaneScaffoldValue , который предоставляет текущее состояние панелей (например, развернуты они или скрыты). Для поведения по умолчанию используйте scaffoldDirective и scaffoldValue навигатора соответственно:

SupportingPaneScaffold(
    directive = navigator.scaffoldDirective,
    value = navigator.scaffoldValue,
    mainPane = { /*...*/ },
    supportingPane = { /*...*/ },
)

Основная и вспомогательная панели представляют собой составные части, содержащие ваш контент. Используйте AnimatedPane , чтобы применить анимацию панели по умолчанию во время навигации. Используйте значение scaffold, чтобы проверить, скрыта ли вспомогательная панель; если да, отобразите кнопку, которая вызывает navigateTo(ThreePaneScaffoldRole.Secondary) для отображения вспомогательной панели.

Вот полная реализация каркаса:

val navigator = rememberSupportingPaneScaffoldNavigator()

BackHandler(navigator.canNavigateBack()) {
    navigator.navigateBack()
}

SupportingPaneScaffold(
    directive = navigator.scaffoldDirective,
    value = navigator.scaffoldValue,
    mainPane = {
        AnimatedPane(modifier = Modifier.safeContentPadding()) {
            // Main pane content
            if (navigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Hidden) {
                Button(
                    modifier = Modifier.wrapContentSize(),
                    onClick = {
                        navigator.navigateTo(SupportingPaneScaffoldRole.Supporting)
                    }
                ) {
                    Text("Show supporting pane")
                }
            } else {
                Text("Supporting pane is shown")
            }
        }
    },
    supportingPane = {
        AnimatedPane(modifier = Modifier.safeContentPadding()) {
            // Supporting pane content
            Text("Supporting pane")
        }
    },
)

Составные элементы панели извлечения

Извлеките отдельные панели SupportingPaneScaffold в отдельные составные элементы, чтобы сделать их пригодными для повторного использования и тестирования. Используйте ThreePaneScaffoldScope для доступа к AnimatedPane если вам нужна анимация по умолчанию:

@Composable
fun ThreePaneScaffoldScope.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")
        }
    }
}

@Composable
fun ThreePaneScaffoldScope.SupportingPane(
    modifier: Modifier = Modifier,
) {
    AnimatedPane(modifier = modifier.safeContentPadding()) {
        // Supporting pane content
        Text("This is the supporting pane")
    }
}

Извлечение панелей в составные элементы упрощает использование SupportingPaneScaffold (сравните следующее с полной реализацией каркаса в предыдущем разделе):

val navigator = rememberSupportingPaneScaffoldNavigator()

BackHandler(navigator.canNavigateBack()) {
    navigator.navigateBack()
}

SupportingPaneScaffold(
    directive = navigator.scaffoldDirective,
    value = navigator.scaffoldValue,
    mainPane = {
        MainPane(
            shouldShowSupportingPaneButton = navigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden,
            onNavigateToSupportingPane = { navigator.navigateTo(ThreePaneScaffoldRole.Secondary) }
        )
    },
    supportingPane = { SupportingPane() },
)