Создайте адаптивную навигацию

Большинство приложений имеют несколько пунктов назначения верхнего уровня, которые доступны через основной навигационный интерфейс приложения. В компактных окнах, например на стандартном дисплее телефона, пункты назначения обычно отображаются на панели навигации в нижней части окна. В расширенном окне, например полноэкранном приложении на планшете, навигационная панель рядом с приложением обычно является лучшим выбором, поскольку к элементам управления навигацией легче добраться, удерживая левую и правую стороны устройства.

NavigationSuiteScaffold упрощает переключение между пользовательскими интерфейсами навигации, отображая соответствующий пользовательский интерфейс навигации, который можно компоновать на основе WindowSizeClass . Сюда входит динамическое изменение пользовательского интерфейса во время изменения размера окна во время выполнения. Поведение по умолчанию — отображение любого из следующих компонентов пользовательского интерфейса:

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

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

NavigationSuiteScaffold является частью библиотеки адаптивной навигации Material3 . Добавьте зависимость для библиотеки в файл build.gradle вашего приложения или модуля:

Котлин


implementation("androidx.compose.material3:material3-adaptive-navigation-suite")

классный


implementation 'androidx.compose.material3:material3-adaptive-navigation-suite'

Создайте эшафот

Двумя основными частями NavigationSuiteScaffold являются элементы навигационного пакета и содержимое выбранного места назначения. Вы можете напрямую определить элементы набора навигации в составном объекте, но обычно они определяются в другом месте, например, в перечислении:

enum class AppDestinations(
    @StringRes val label: Int,
    val icon: ImageVector,
    @StringRes val contentDescription: Int
) {
    HOME(R.string.home, Icons.Default.Home, R.string.home),
    FAVORITES(R.string.favorites, Icons.Default.Favorite, R.string.favorites),
    SHOPPING(R.string.shopping, Icons.Default.ShoppingCart, R.string.shopping),
    PROFILE(R.string.profile, Icons.Default.AccountBox, R.string.profile),
}

Чтобы использовать NavigationSuiteScaffold , вы должны отслеживать текущий пункт назначения, что можно сделать с помощью rememberSaveable :

var currentDestination by rememberSaveable { mutableStateOf(AppDestinations.HOME) }

В следующем примере параметр navigationSuiteItems (тип NavigationSuiteScope использует свою функцию item для определения пользовательского интерфейса навигации для отдельного пункта назначения. Пользовательский интерфейс назначения используется на панелях навигации, направляющих и ящиках. Чтобы создать элементы навигации, вы перебираете AppDestinations ( определенное в предыдущем фрагменте):

NavigationSuiteScaffold(
    navigationSuiteItems = {
        AppDestinations.entries.forEach {
            item(
                icon = {
                    Icon(
                        it.icon,
                        contentDescription = stringResource(it.contentDescription)
                    )
                },
                label = { Text(stringResource(it.label)) },
                selected = it == currentDestination,
                onClick = { currentDestination = it }
            )
        }
    }
) {
    // TODO: Destination content.
}

В лямбде целевого содержимого используйте значение currentDestination , чтобы решить, какой пользовательский интерфейс отображать. Если вы используете библиотеку навигации в своем приложении, используйте ее здесь, чтобы отобразить соответствующий пункт назначения. Оператора When может быть достаточно:

NavigationSuiteScaffold(
    navigationSuiteItems = { /*...*/ }
) {
    // Destination content.
    when (currentDestination) {
        AppDestinations.HOME -> HomeDestination()
        AppDestinations.FAVORITES -> FavoritesDestination()
        AppDestinations.SHOPPING -> ShoppingDestination()
        AppDestinations.PROFILE -> ProfileDestination()
    }
}

Изменить цвета

NavigationSuiteScaffold создает Surface по всей области, которую занимает каркас, обычно по всему окну. Кроме того, scaffold рисует конкретный пользовательский интерфейс навигации, например NavigationBar . И поверхность, и пользовательский интерфейс навигации используют значения, указанные в теме вашего приложения, но вы можете переопределить значения темы.

Параметр containerColor определяет цвет поверхности. По умолчанию используется цвет фона вашей цветовой схемы. Параметр contentColor определяет цвет содержимого на этой поверхности. По умолчанию используется цвет «включен» для всего, что указано для containerColor . Например, containerColor использует цвет background , то contentColor использует цвет onBackground . Дополнительные сведения о том, как работает цветовая система, см. в разделе «Темы Material Design 3» в Compose. При переопределении этих значений используйте значения, определенные в вашей теме, чтобы ваше приложение поддерживало темный и светлый режимы отображения:

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    containerColor = MaterialTheme.colorScheme.primary,
    contentColor = MaterialTheme.colorScheme.onPrimary,
) {
    // Content...
}

Пользовательский интерфейс навигации отображается перед поверхностью NavigationSuiteScaffold . Значения по умолчанию для цветов пользовательского интерфейса предоставляются NavigationSuiteDefaults.colors() , но вы также можете переопределить эти значения. Например, если вы хотите, чтобы фон панели навигации был прозрачным, а остальные значения были значениями по умолчанию, переопределите navigationBarContainerColor :

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    navigationSuiteColors = NavigationSuiteDefaults.colors(
        navigationBarContainerColor = Color.Transparent,
    )
) {
    // Content...
}

В конечном итоге вы можете настроить каждый элемент пользовательского интерфейса навигации. При вызове функции item вы можете передать экземпляр NavigationSuiteItemColors . Класс определяет цвета элементов на панели навигации, направляющей навигации и панели навигации. Это означает, что вы можете использовать одинаковые цвета для каждого типа пользовательского интерфейса навигации или можете варьировать цвета в зависимости от ваших потребностей. Определите цвета на уровне NavigationSuiteScaffold , чтобы использовать один и тот же экземпляр объекта для всех элементов, и вызовите функцию NavigationSuiteDefaults.itemColors() чтобы переопределить только те, которые вы хотите изменить:

val myNavigationSuiteItemColors = NavigationSuiteDefaults.itemColors(
    navigationBarItemColors = NavigationBarItemDefaults.colors(
        indicatorColor = MaterialTheme.colorScheme.primaryContainer,
        selectedIconColor = MaterialTheme.colorScheme.onPrimaryContainer
    ),
)

NavigationSuiteScaffold(
    navigationSuiteItems = {
        AppDestinations.entries.forEach {
            item(
                icon = {
                    Icon(
                        it.icon,
                        contentDescription = stringResource(it.contentDescription)
                    )
                },
                label = { Text(stringResource(it.label)) },
                selected = it == currentDestination,
                onClick = { currentDestination = it },
                colors = myNavigationSuiteItemColors,
            )
        }
    },
) {
    // Content...
}

Настройка типов навигации

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

val adaptiveInfo = currentWindowAdaptiveInfo()
val customNavSuiteType = with(adaptiveInfo) {
    if (windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.EXPANDED) {
        NavigationSuiteType.NavigationDrawer
    } else {
        NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(adaptiveInfo)
    }
}

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    layoutType = customNavSuiteType,
) {
    // Content...
}

Дополнительные ресурсы

См. руководство по Material Design:

См. следующие компоненты библиотеки androidx.compose.material3 :