NavigationSuiteScaffold:导航栏与导航轨自动切换 · AndroidX 源码指南
AAndroidX 源码指南
自适应布局
自适应布局 · androidx.window

NavigationSuiteScaffold:导航栏与导航轨自动切换Window 1.6.0-alpha05

让顶层目的地随窗口使用合适的 Material 导航组件。

最后更新 2026-08-01

复制即用

@Composable
fun AppShell(destinations: List<Destination>) {
    var selected by rememberSaveable { mutableIntStateOf(0) }

    NavigationSuiteScaffold(
        navigationItems = {
            destinations.forEachIndexed { index, destination ->
                NavigationSuiteItem(
                    icon = { Icon(destination.icon, contentDescription = null) },
                    label = { Text(destination.label) },
                    selected = selected == index,
                    onClick = { selected = index },
                )
            }
        },
    ) {
        DestinationContent(destinations[selected])
    }
}

它解决什么

Navigation Suite 面向应用的顶层目的地,根据窗口自适应信息自动选择:

窗口呈现
窄(Compact)底部导航栏
中宽(Medium/Expanded)侧边导航轨(Rail)
宽/桌面展开的导航轨

边界:它解决导航控件形态,不会替你管理业务 back stack——示例的 selected 在真实应用里来自 Navigation 2/3 的当前位置。

与真实导航集成

// Navigation 3 示例:selected 来自 backStack
@Composable
fun AppShell(backStack: List<Any>, onSelect: (Any) -> Unit) {
    NavigationSuiteScaffold(
        navigationItems = {
            destinations.forEach { dest ->
                NavigationSuiteItem(
                    icon = { Icon(dest.icon, null) },
                    label = { Text(dest.label) },
                    selected = backStack.lastOrNull() == dest.key,
                    onClick = { onSelect(dest.key) },
                )
            }
        },
    ) { /* 当前目的地内容 */ }
}

覆写默认类型

NavigationSuiteScaffold(
    navigationSuiteType = NavigationSuiteType.WideNavigationRail,
    navigationItems = { ... },
)

先理解默认结果再覆写:

val default = NavigationSuiteScaffoldDefaults.navigationSuiteType(
    currentWindowAdaptiveInfoV2()
)

不要仅凭横竖屏决定 rail/bar——分屏窗口会让判断失效。

常见陷阱

  • selected 与导航脱节:UI 高亮和实际目的地不一致。
  • 设备名判断if (isTablet) 不如窗口尺寸可靠。
  • 覆写类型无依据:先看默认值再改,别拍脑袋。
  • 忽略分屏:窗口变化要响应,否则布局错位。

复制即用

@Composable
fun AdaptiveNavigationShell(
    destinations: List<NavigationDestination>,
    current: Any?,
    onSelect: (Any) -> Unit,
) {
    NavigationSuiteScaffold(
        navigationSuiteType = remember {
            NavigationSuiteScaffoldDefaults.navigationSuiteType(currentWindowAdaptiveInfoV2())
        },
        navigationItems = {
            destinations.forEach { dest ->
                NavigationSuiteItem(
                    icon = { Icon(dest.icon, contentDescription = dest.label) },
                    label = { Text(dest.label) },
                    selected = current == dest.key,
                    onClick = { onSelect(dest.key) },
                )
            }
        },
    ) {
        DestinationContent(current)
    }
}

要点

  • 按窗口自动切换底部栏/导航轨;顶层目的地专用。
  • selected 来自真实导航状态,不另起炉灶。
  • 覆写类型先看默认值;别用横竖屏/设备名判断。
  • 分屏/旋转要响应窗口变化。

相关页面