大多数应用程序都有几个顶级目的地,可以通过应用程序的主要导航 UI 访问。在紧凑的窗口中,例如标准手机显示屏,这些目的地通常显示在窗口底部的导航栏中。在扩展窗口中,例如平板电脑上的全屏应用程序,导航栏通常是更好的选择,因为在握住设备的左右两侧时,导航控件更容易触及。
NavigationSuiteScaffold
通过根据 WindowSizeClass
显示适当的导航 UI 可组合元素,简化了导航 UI 之间的切换。这包括在运行时窗口大小更改期间动态更改 UI。默认行为是显示以下 UI 组件之一
- 导航栏 如果宽度或高度是紧凑的,或者设备处于桌面姿势
- 导航栏 用于其他所有情况
添加依赖项
NavigationSuiteScaffold
是 Material3 自适应导航套件 库的一部分。在应用程序或模块的 build.gradle
文件中添加库的依赖项
Kotlin
implementation("androidx.compose.material3:material3-adaptive-navigation-suite")
Groovy
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
函数为单个目的地定义导航 UI。目的地 UI 用于导航栏、栏和抽屉。要创建导航项目,请循环遍历您的 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. }
在目的地内容 lambda 中,使用 currentDestination
值来决定要显示哪个 UI。如果您在应用程序中使用导航库,请在此处使用它来显示适当的目的地。when 语句就足够了
NavigationSuiteScaffold( navigationSuiteItems = { /*...*/ } ) { // Destination content. when (currentDestination) { AppDestinations.HOME -> HomeDestination() AppDestinations.FAVORITES -> FavoritesDestination() AppDestinations.SHOPPING -> ShoppingDestination() AppDestinations.PROFILE -> ProfileDestination() } }
更改颜色
NavigationSuiteScaffold
在脚手架占据的整个区域(通常是整个窗口)上创建一个 Surface
。在它的上面,脚手架绘制特定的导航 UI,例如 NavigationBar
。表面和导航 UI 都使用您应用程序主题中指定的 value,但您可以覆盖主题 value。
containerColor
参数指定表面的颜色。默认值是您颜色方案的背景颜色。contentColor
参数指定该表面上内容的颜色。默认值是为 containerColor
指定的任何内容的“on”颜色。例如,如果 containerColor
使用 background
颜色,则 contentColor
使用 onBackground
颜色。有关颜色系统工作原理的更多详细信息,请参阅 Compose 中的 Material Design 3 主题。覆盖这些 value 时,请使用您主题中定义的 value,以便您的应用程序支持黑暗和明亮显示模式
NavigationSuiteScaffold( navigationSuiteItems = { /* ... */ }, containerColor = MaterialTheme.colorScheme.primary, contentColor = MaterialTheme.colorScheme.onPrimary, ) { // Content... }
导航 UI 绘制在 NavigationSuiteScaffold
表面前面。UI 颜色的默认值由 NavigationSuiteDefaults.colors()
提供,但您也可以覆盖这些 value。例如,如果您希望导航栏的背景透明,但其他 value 为默认值,则覆盖 navigationBarContainerColor
NavigationSuiteScaffold( navigationSuiteItems = { /* ... */ }, navigationSuiteColors = NavigationSuiteDefaults.colors( navigationBarContainerColor = Color.Transparent, ) ) { // Content... }
最终,您可以自定义导航 UI 中的每个项目。调用 item
函数时,您可以传入 NavigationSuiteItemColors
的实例。该类指定导航栏、导航栏和导航抽屉中项目的颜色。这意味着您可以使每个导航 UI 类型的颜色相同,或者根据您的需要更改颜色。在 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
的默认行为会根据 窗口大小类 更改导航 UI。但是,您可能希望覆盖此行为。例如,如果您的应用程序为 feed 显示一个大的内容面板,则该应用程序可以使用永久导航抽屉来扩展窗口,但仍然回退到紧凑和中等窗口大小类的默认行为
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
库组件