自适应布局
自适应布局 · 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 来自真实导航状态,不另起炉灶。
- 覆写类型先看默认值;别用横竖屏/设备名判断。
- 分屏/旋转要响应窗口变化。