NavigationBar
NavigationBar 是 COUI 中的底部导航栏组件,用于在应用底部创建导航菜单,支持 2 到 5 个导航项,提供不同的显示模式(仅图标、仅文本、图标和文本、仅选中项显示文本)。
FloatingNavigationBar 是一个悬浮样式的底部导航栏组件,同样支持 2 到 5 个导航项,仅显示图标。
这些组件通常与 Scaffold 组件结合使用,以便在应用程序的不同页面中保持一致的布局和行为。
引入
import io.github.suqi8.coui.kmp.basic.NavigationBar
import io.github.suqi8.coui.kmp.basic.NavigationBarItem
import io.github.suqi8.coui.kmp.basic.FloatingNavigationBar
import io.github.suqi8.coui.kmp.basic.FloatingNavigationBarItem
import io.github.suqi8.coui.kmp.basic.NavigationBarDisplayMode
import io.github.suqi8.coui.kmp.basic.NavigationItem基本用法
NavigationBar
NavigationBar 组件可用于创建固定在底部的导航菜单:
var selectedIndex by remember { mutableStateOf(0) }
val items = listOf("Home", "Profile", "Settings")
val icons = listOf(COUIIcons.VerticalSplit, COUIIcons.Contacts, COUIIcons.Settings)
Scaffold(
bottomBar = {
NavigationBar {
items.forEachIndexed { index, label ->
NavigationBarItem(
selected = selectedIndex == index,
onClick = { selectedIndex = index },
icon = icons[index],
label = label
)
}
}
}
)FloatingNavigationBar
FloatingNavigationBar 组件可用于创建悬浮在底部的导航菜单:
var selectedIndex by remember { mutableStateOf(0) }
val items = listOf("Home", "Profile", "Settings")
val icons = listOf(COUIIcons.VerticalSplit, COUIIcons.Contacts, COUIIcons.Settings)
Scaffold(
bottomBar = {
FloatingNavigationBar {
items.forEachIndexed { index, label ->
FloatingNavigationBarItem(
selected = selectedIndex == index,
onClick = { selectedIndex = index },
icon = icons[index],
label = label
)
}
}
}
)组件状态
选中状态
NavigationBarItem 遵循 COUI tab 导航的状态模型:选中项的图标与标签以完整标签色显示,未选中项呈暗化色;图标在两种状态间以 180ms 交叉淡变过渡,标签颜色则瞬时切换。标签始终使用 Medium 字重;按压未选中项时图标会预览选中色。FloatingNavigationBarItem 在选中时高亮图标。
属性
NavigationBar 属性
| 属性名 | 类型 | 说明 | 默认值 | 是否必须 |
|---|---|---|---|---|
| modifier | Modifier | 应用于导航栏的修饰符 | Modifier | 否 |
| color | Color | 导航栏背景颜色 | COUITheme.colorScheme.background | 否 |
| showDivider | Boolean | 是否显示顶部分割线 | true | 否 |
| defaultWindowInsetsPadding | Boolean | 是否应用默认窗口嵌入边距 | true | 否 |
| mode | NavigationBarDisplayMode | 导航项的显示模式 | NavigationBarDisplayMode.IconAndText | 否 |
| content | @Composable RowScope.() | 导航栏的内容 | - | 是 |
NavigationBarItem 属性
| 属性名 | 类型 | 说明 | 默认值 | 是否必须 |
|---|---|---|---|---|
| selected | Boolean | 是否选中 | - | 是 |
| onClick | () -> Unit | 点击时的回调 | - | 是 |
| icon | ImageVector | 图标 | - | 是 |
| label | String | 文本标签 | - | 是 |
| modifier | Modifier | 应用于导航项的修饰符 | Modifier | 否 |
| enabled | Boolean | 是否启用 | true | 否 |
FloatingNavigationBar 属性
| 属性名 | 类型 | 说明 | 默认值 | 是否必须 |
|---|---|---|---|---|
| modifier | Modifier | 应用于导航栏的修饰符 | Modifier | 否 |
| color | Color | 导航栏背景颜色 | COUITheme.colorScheme.surfaceContainer | 否 |
| cornerRadius | Dp | 导航栏的圆角半径 | FloatingToolbarDefaults.CornerRadius | 否 |
| horizontalAlignment | Alignment.Horizontal | 导航栏在其父容器中的水平对齐方式 | CenterHorizontally | 否 |
| horizontalOutSidePadding | Dp | 导航栏外部的水平内边距 | FloatingNavigationBarDefaults.HorizontalOutSidePadding | 否 |
| shadowElevation | Dp | 导航栏的阴影高度 | FloatingNavigationBarDefaults.ShadowElevation | 否 |
| showDivider | Boolean | 是否显示导航栏周围的分割线 | false | 否 |
| defaultWindowInsetsPadding | Boolean | 是否应用默认窗口嵌入边距 | true | 否 |
| content | @Composable () -> Unit | 导航栏的内容 | - | 是 |
FloatingNavigationBarItem 属性
| 属性名 | 类型 | 说明 | 默认值 | 是否必须 |
|---|---|---|---|---|
| selected | Boolean | 是否选中 | - | 是 |
| onClick | () -> Unit | 点击时的回调 | - | 是 |
| icon | ImageVector | 图标 | - | 是 |
| label | String | 文本标签 | - | 是 |
| modifier | Modifier | 应用于导航项的修饰符 | Modifier | 否 |
| enabled | Boolean | 是否启用 | true | 否 |
NavigationBarDefaults 对象
NavigationBarDefaults 对象提供了 NavigationBar 和 NavigationBarItem 组件的默认值。
常量
| 常量名 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| ItemHeight | Dp | 项目单元高度 | 56.dp |
| HorizontalPadding | Dp | 栏两侧的水平内边距 | 12.dp |
| ItemHorizontalPadding | Dp | 项目单元内部水平内边距 | 2.dp |
| IconSize | Dp | 图标尺寸 | 24.dp |
| IconTopPadding | Dp | 图标顶部内边距 | 9.dp |
| LabelBottomPadding | Dp | 标签底部内边距 | 7.dp |
| LabelFontSize | TextUnit | 标签字号 | 10.sp |
| TextFontSize | TextUnit | 字号(TextOnly 模式) | 14.sp |
| IconFadeDurationMillis | Int | 图标状态间交叉淡变时长 | 180 |
FloatingNavigationBarDefaults 对象
FloatingNavigationBarDefaults 对象提供了 FloatingNavigationBar 和 FloatingNavigationBarItem 组件的默认值。
常量
| 常量名 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| HorizontalOutSidePadding | Dp | 外部水平内边距 | 36.dp |
| ShadowElevation | Dp | 阴影高度 | 1.dp |
| HorizontalPadding | Dp | 内部水平内边距 | 12.dp |
| ItemSpacing | Dp | 项目间距 | 12.dp |
| IconSize | Dp | 图标尺寸 | 28.dp |
| IconPadding | Dp | 图标周围的内边距 | 10.dp |
| SelectedPressedAlpha | Float | 选中项按压时的透明度 | 0.5f |
| UnselectedPressedAlpha | Float | 未选中项按压时的透明度 | 0.6f |
| UnselectedAlpha | Float | 未选中项的透明度 | 0.4f |
NavigationBarDisplayMode 枚举
| 值 | 说明 |
|---|---|
| IconAndText | 显示图标和文本 |
| IconOnly | 仅显示图标 |
| TextOnly | 仅显示文本 |
| IconWithSelectedLabel | 始终显示图标,仅选中时显示文本 |
设置在 NavigationBar 上的显示模式会通过 LocalNavigationBarDisplayMode 组合局部值传递给各导航项。FloatingNavigationBar 没有 mode 参数——其导航项始终仅显示图标。
NavigationItem 属性
NavigationItem 是一个用于承载导航项标签与图标的便捷数据类。
| 属性名 | 类型 | 说明 | 默认值 | 是否必须 |
|---|---|---|---|---|
| label | String | 该项的标签 | - | 是 |
| icon | ImageVector | 该项的图标 | - | 是 |
进阶用法
NavigationBar
自定义颜色
NavigationBar(
color = Color.Red.copy(alpha = 0.3f)
) {
// ... items ...
}无分割线
NavigationBar(
showDivider = false
) {
// ... items ...
}处理窗口边距
NavigationBar(
defaultWindowInsetsPadding = false // Handle window insets padding manually
) {
// ... items ...
}显示模式
NavigationBar(
// IconAndText (default) / IconOnly / TextOnly / IconWithSelectedLabel
mode = NavigationBarDisplayMode.IconWithSelectedLabel
) {
// ... items ...
}FloatingNavigationBar
自定义颜色和圆角
FloatingNavigationBar(
color = COUITheme.colorScheme.primaryContainer,
cornerRadius = 28.dp
) {
// ... items ...
}自定义对齐和边距
FloatingNavigationBar(
horizontalAlignment = Alignment.Start, // Align to start
horizontalOutSidePadding = 16.dp // Set outside padding
) {
// ... items ...
}分割线与阴影
FloatingNavigationBar(
showDivider = true, // Draw a thin divider ring around the bar
shadowElevation = 0.dp // Disable the drop shadow
) {
// ... items ...
}结合页面切换使用(使用脚手架)
使用 NavigationBar
val pages = listOf("Home", "Profile", "Settings")
val icons = listOf(COUIIcons.VerticalSplit, COUIIcons.Contacts, COUIIcons.Settings)
var selectedIndex by remember { mutableStateOf(0) }
Scaffold(
bottomBar = {
NavigationBar {
pages.forEachIndexed { index, label ->
NavigationBarItem(
selected = selectedIndex == index,
onClick = { selectedIndex = index },
icon = icons[index],
label = label
)
}
}
}
) { paddingValues ->
// Content area needs to consider padding
Box(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues),
contentAlignment = Alignment.Center
) {
Text(
text = "Current Page: ${pages[selectedIndex]}",
style = COUITheme.textStyles.title1
)
}
}使用 FloatingNavigationBar
val pages = listOf("Home", "Profile", "Settings")
val icons = listOf(COUIIcons.VerticalSplit, COUIIcons.Contacts, COUIIcons.Settings)
var selectedIndex by remember { mutableStateOf(0) }
Scaffold(
bottomBar = {
FloatingNavigationBar {
pages.forEachIndexed { index, label ->
FloatingNavigationBarItem(
selected = selectedIndex == index,
onClick = { selectedIndex = index },
icon = icons[index],
label = label
)
}
}
}
) { paddingValues ->
// Content area needs to consider padding
Box(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues),
contentAlignment = Alignment.Center
) {
Text(
text = "Current Page: ${pages[selectedIndex]}",
style = COUITheme.textStyles.title1
)
}
}
