大多数应用都有几个顶级目的地,这些目的地可以通过应用的主要导航界面访问。在紧凑型窗口(例如标准手机显示屏)中,目的地通常显示在窗口底部的导航栏中。在展开型窗口(例如平板电脑上的全屏应用)中,应用旁边的导航边栏通常是更好的选择,因为在握持设备的左右两侧时,导航控件更容易触及。
NavigationSuiteScaffold
通过根据 WindowSizeClass
显示相应的导航界面可组合项,简化了导航界面之间的切换。这包括在运行时窗口大小更改期间动态更改界面。默认行为是显示以下任一界面组件:
- 如果宽度或高度紧凑,或设备处于桌面姿态,则为导航栏
- 其他情况则为导航边栏

NavigationSuiteScaffold
在紧凑型窗口中显示导航栏。
NavigationSuiteScaffold
在展开型窗口中显示导航边栏。添加依赖项
NavigationSuiteScaffold
是 Material3 自适应导航套件库的一部分。在您的应用或模块的 build.gradle
文件中添加此库的依赖项:
Kotlin
implementation("androidx.compose.material3:material3-adaptive-navigation-suite")
Groovy
implementation 'androidx.compose.material3:material3-adaptive-navigation-suite'
创建 Scaffold
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. }
在目的地内容 lambda 中,使用 currentDestination
值来决定显示哪个界面。如果您在应用中使用导航库,请在此处使用它来显示相应的目的地。使用 when 语句即可:
NavigationSuiteScaffold( navigationSuiteItems = { /*...*/ } ) { // Destination content. when (currentDestination) { AppDestinations.HOME -> HomeDestination() AppDestinations.FAVORITES -> FavoritesDestination() AppDestinations.SHOPPING -> ShoppingDestination() AppDestinations.PROFILE -> ProfileDestination() } }
更改颜色
NavigationSuiteScaffold
在 scaffold 占据的整个区域(通常是整个窗口)上创建一个 Surface
。在此之上,scaffold 会绘制特定的导航界面,例如 NavigationBar
。Surface 和导航界面都使用应用主题中指定的值,但您可以覆盖主题值。
containerColor
参数指定 Surface 的颜色。默认值为配色方案的背景颜色。contentColor
参数指定该 Surface 上的内容的颜色。默认值是 containerColor
指定的颜色的“on”颜色。例如,如果 containerColor
使用 background
颜色,则 contentColor
使用 onBackground
颜色。有关颜色系统如何工作的更多详细信息,请参阅Compose 中的 Material Design 3 主题设置。覆盖这些值时,请使用主题中定义的值,以便您的应用支持深色和浅色显示模式:
NavigationSuiteScaffold( navigationSuiteItems = { /* ... */ }, containerColor = MaterialTheme.colorScheme.primary, contentColor = MaterialTheme.colorScheme.onPrimary, ) { // Content... }
导航界面绘制在 NavigationSuiteScaffold
Surface 的前面。界面颜色的默认值由 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
的默认行为是根据窗口大小类更改导航界面。但是,您可能需要覆盖此行为。例如,如果您的应用显示一个包含大量 Feed 内容的单个大窗格,则该应用可以对展开的窗口使用永久性导航抽屉式菜单,但对于紧凑和中等窗口大小类仍可回退到默认行为:
val adaptiveInfo = currentWindowAdaptiveInfo() val customNavSuiteType = with(adaptiveInfo) { if (windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_EXPANDED_LOWER_BOUND)) { NavigationSuiteType.NavigationDrawer } else { NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(adaptiveInfo) } } NavigationSuiteScaffold( navigationSuiteItems = { /* ... */ }, layoutType = customNavSuiteType, ) { // Content... }
其他资源
Material Design 指南
androidx.compose.material3
库组件