跳转到内容

NavigationBar

NavigationBar 是 COUI 中的底部导航栏组件,用于在应用底部创建导航菜单,支持 2 到 5 个导航项,提供不同的显示模式(仅图标、仅文本、图标和文本、仅选中项显示文本)。

FloatingNavigationBar 是一个悬浮样式的底部导航栏组件,同样支持 2 到 5 个导航项,仅显示图标。

这些组件通常与 Scaffold 组件结合使用,以便在应用程序的不同页面中保持一致的布局和行为。

引入

kotlin
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 组件可用于创建固定在底部的导航菜单:

kotlin
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 组件可用于创建悬浮在底部的导航菜单:

kotlin
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 在选中时高亮图标。

属性

属性名类型说明默认值是否必须
modifierModifier应用于导航栏的修饰符Modifier
colorColor导航栏背景颜色COUITheme.colorScheme.background
showDividerBoolean是否显示顶部分割线true
defaultWindowInsetsPaddingBoolean是否应用默认窗口嵌入边距true
modeNavigationBarDisplayMode导航项的显示模式NavigationBarDisplayMode.IconAndText
content@Composable RowScope.()导航栏的内容-
属性名类型说明默认值是否必须
selectedBoolean是否选中-
onClick() -> Unit点击时的回调-
iconImageVector图标-
labelString文本标签-
modifierModifier应用于导航项的修饰符Modifier
enabledBoolean是否启用true

FloatingNavigationBar 属性

属性名类型说明默认值是否必须
modifierModifier应用于导航栏的修饰符Modifier
colorColor导航栏背景颜色COUITheme.colorScheme.surfaceContainer
cornerRadiusDp导航栏的圆角半径FloatingToolbarDefaults.CornerRadius
horizontalAlignmentAlignment.Horizontal导航栏在其父容器中的水平对齐方式CenterHorizontally
horizontalOutSidePaddingDp导航栏外部的水平内边距FloatingNavigationBarDefaults.HorizontalOutSidePadding
shadowElevationDp导航栏的阴影高度FloatingNavigationBarDefaults.ShadowElevation
showDividerBoolean是否显示导航栏周围的分割线false
defaultWindowInsetsPaddingBoolean是否应用默认窗口嵌入边距true
content@Composable () -> Unit导航栏的内容-

FloatingNavigationBarItem 属性

属性名类型说明默认值是否必须
selectedBoolean是否选中-
onClick() -> Unit点击时的回调-
iconImageVector图标-
labelString文本标签-
modifierModifier应用于导航项的修饰符Modifier
enabledBoolean是否启用true

NavigationBarDefaults 对象提供了 NavigationBar 和 NavigationBarItem 组件的默认值。

常量

常量名类型说明默认值
ItemHeightDp项目单元高度56.dp
HorizontalPaddingDp栏两侧的水平内边距12.dp
ItemHorizontalPaddingDp项目单元内部水平内边距2.dp
IconSizeDp图标尺寸24.dp
IconTopPaddingDp图标顶部内边距9.dp
LabelBottomPaddingDp标签底部内边距7.dp
LabelFontSizeTextUnit标签字号10.sp
TextFontSizeTextUnit字号(TextOnly 模式)14.sp
IconFadeDurationMillisInt图标状态间交叉淡变时长180

FloatingNavigationBarDefaults 对象

FloatingNavigationBarDefaults 对象提供了 FloatingNavigationBar 和 FloatingNavigationBarItem 组件的默认值。

常量

常量名类型说明默认值
HorizontalOutSidePaddingDp外部水平内边距36.dp
ShadowElevationDp阴影高度1.dp
HorizontalPaddingDp内部水平内边距12.dp
ItemSpacingDp项目间距12.dp
IconSizeDp图标尺寸28.dp
IconPaddingDp图标周围的内边距10.dp
SelectedPressedAlphaFloat选中项按压时的透明度0.5f
UnselectedPressedAlphaFloat未选中项按压时的透明度0.6f
UnselectedAlphaFloat未选中项的透明度0.4f
说明
IconAndText显示图标和文本
IconOnly仅显示图标
TextOnly仅显示文本
IconWithSelectedLabel始终显示图标,仅选中时显示文本

设置在 NavigationBar 上的显示模式会通过 LocalNavigationBarDisplayMode 组合局部值传递给各导航项。FloatingNavigationBar 没有 mode 参数——其导航项始终仅显示图标。

NavigationItem 是一个用于承载导航项标签与图标的便捷数据类。

属性名类型说明默认值是否必须
labelString该项的标签-
iconImageVector该项的图标-

进阶用法

自定义颜色

kotlin
NavigationBar(
    color = Color.Red.copy(alpha = 0.3f)
) {
    // ... items ...
}

无分割线

kotlin
NavigationBar(
    showDivider = false
) {
    // ... items ...
}

处理窗口边距

kotlin
NavigationBar(
    defaultWindowInsetsPadding = false // Handle window insets padding manually
) {
    // ... items ...
}

显示模式

kotlin
NavigationBar(
    // IconAndText (default) / IconOnly / TextOnly / IconWithSelectedLabel
    mode = NavigationBarDisplayMode.IconWithSelectedLabel
) {
    // ... items ...
}

FloatingNavigationBar

自定义颜色和圆角

kotlin
FloatingNavigationBar(
    color = COUITheme.colorScheme.primaryContainer,
    cornerRadius = 28.dp
) {
    // ... items ...
}

自定义对齐和边距

kotlin
FloatingNavigationBar(
    horizontalAlignment = Alignment.Start, // Align to start
    horizontalOutSidePadding = 16.dp // Set outside padding
) {
    // ... items ...
}

分割线与阴影

kotlin
FloatingNavigationBar(
    showDivider = true, // Draw a thin divider ring around the bar
    shadowElevation = 0.dp // Disable the drop shadow
) {
    // ... items ...
}

结合页面切换使用(使用脚手架)

使用 NavigationBar

kotlin
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

kotlin
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
        )
    }
}

变更日志

基于 Apache-2.0 许可发布