跳转到内容

NavigationBar ​

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

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

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

引入 ​

kotlin
import top.yukonga.miuix.kmp.basic.NavigationBar
import top.yukonga.miuix.kmp.basic.NavigationBarDefaults
import top.yukonga.miuix.kmp.basic.NavigationBarItem
import top.yukonga.miuix.kmp.basic.FloatingNavigationBar
import top.yukonga.miuix.kmp.basic.FloatingNavigationBarItem
import top.yukonga.miuix.kmp.basic.NavigationBarDisplayMode

基本用法 ​

NavigationBar 组件可用于创建固定在底部的导航菜单:

kotlin
var selectedIndex by remember { mutableStateOf(0) }
val items = listOf("首页", "我的", "设置")
val icons = listOf(MiuixIcons.VerticalSplit, MiuixIcons.Contacts, MiuixIcons.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("首页", "我的", "设置")
val icons = listOf(MiuixIcons.VerticalSplit, MiuixIcons.Contacts, MiuixIcons.Settings)

Scaffold(
    bottomBar = {
        FloatingNavigationBar {
            items.forEachIndexed { index, label ->
                FloatingNavigationBarItem(
                    selected = selectedIndex == index,
                    onClick = { selectedIndex = index },
                    icon = icons[index],
                    label = label
                )
            }
        }
    }
)

自定义颜色 ​

两种导航项都支持通过 NavigationBarDefaults.navigationBarItemColors() 创建的 colors。例如,使用主题主色显示选中项:

kotlin
val itemColors = NavigationBarDefaults.navigationBarItemColors(
    unselectedContentColor = MiuixTheme.colorScheme.onSurfaceContainer,
    selectedContentColor = MiuixTheme.colorScheme.primary,
)

NavigationBar {
    items.forEachIndexed { index, label ->
        NavigationBarItem(
            selected = selectedIndex == index,
            onClick = { selectedIndex = index },
            icon = icons[index],
            label = label,
            colors = itemColors,
        )
    }
}

在 FloatingNavigationBar 内向 FloatingNavigationBarItem 传入同样的 colors = itemColors,即可自定义其图标颜色。

传入的颜色是基础颜色:未选中时 alpha 乘以 0.4,未选中且按下时乘以 0.6,选中且按下时乘以 0.5。选中且未按下时直接使用传入的颜色。Color.Transparent 在所有状态下均保持透明。

组件状态 ​

选中状态 ​

NavigationBarItem 会自动处理选中项的视觉样式,选中项将显示粗体文本并高亮图标/文本。FloatingNavigationBarItem 在选中时高亮图标。

属性 ​

属性名类型说明默认值是否必须
modifierModifier应用于导航栏的修饰符Modifier否
colorColor导航栏背景颜色MiuixTheme.colorScheme.surface否
showDividerBoolean是否显示顶部分割线true否
defaultWindowInsetsPaddingBoolean是否应用默认窗口嵌入边距true否
modeNavigationBarDisplayMode导航项的显示模式NavigationBarDisplayMode.IconAndText否
content@Composable RowScope.()导航栏的内容-是
属性名类型说明默认值是否必须
selectedBoolean是否选中-是
onClick() -> Unit点击时的回调-是
iconImageVector图标-是
labelString文本标签-是
modifierModifier应用于导航项的修饰符Modifier否
enabledBoolean是否启用true否
colorsNavigationBarItemColors图标和文本的基础颜色NavigationBarDefaults.navigationBarItemColors()否
badge(@Composable () -> Unit)?显示在该项图标上的可选徽章,通常是一个 Badgenull否

FloatingNavigationBar 属性 ​

属性名类型说明默认值是否必须
modifierModifier应用于导航栏的修饰符Modifier否
colorColor导航栏背景颜色MiuixTheme.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否
colorsNavigationBarItemColors图标和文本的基础颜色NavigationBarDefaults.navigationBarItemColors()否
badge(@Composable () -> Unit)?显示在该项图标上的可选徽章,通常是一个 Badgenull否

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

常量 ​

常量名类型说明默认值
ItemHeightDp项目高度64.dp
IconSizeDp图标尺寸26.dp
LabelFontSizeTextUnit标签字号12.sp
IconTopPaddingDp图标顶部内边距8.dp
BottomPaddingDp标签底部内边距8.dp
SelectedPressedAlphaFloat选中项按压时的透明度0.5f
UnselectedPressedAlphaFloat未选中项按压时的透明度0.6f
UnselectedAlphaFloat未选中项的透明度0.4f

此可组合工厂函数返回通过 remember 缓存的 NavigationBarItemColors,供两种导航项共用。不传入 colors 时保持默认主题效果。

参数类型说明默认值
unselectedContentColorColor未选中内容的基础颜色MiuixTheme.colorScheme.onSurfaceContainer
selectedContentColorColor选中内容的基础颜色MiuixTheme.colorScheme.onSurfaceContainer

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仅显示图标
IconWithSelectedLabel始终显示图标,仅选中时显示文本

进阶用法 ​

自定义颜色 ​

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

无分割线 ​

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

处理窗口边距 ​

kotlin
NavigationBar(
    defaultWindowInsetsPadding = false // 自行处理窗口嵌入边距
) {
    // ... items ...
}

FloatingNavigationBar ​

自定义颜色和圆角 ​

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

自定义对齐和边距 ​

kotlin
FloatingNavigationBar(
    horizontalAlignment = Alignment.Start, // 左对齐
    horizontalOutSidePadding = 16.dp // 设置外部边距
) {
    // ... items ...
}

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

使用 NavigationBar ​

kotlin
val pages = listOf("首页", "我的", "设置")
val icons = listOf(MiuixIcons.VerticalSplit, MiuixIcons.Contacts, MiuixIcons.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 ->
    // 内容区域需要考虑 padding
    Box(
        modifier = Modifier
            .fillMaxSize()
            .padding(paddingValues),
        contentAlignment = Alignment.Center
    ) {
        Text(
            text = "当前页面:${pages[selectedIndex]}",
            style = MiuixTheme.textStyles.title1
        )
    }
}

使用 FloatingNavigationBar ​

kotlin
val pages = listOf("首页", "我的", "设置")
val icons = listOf(MiuixIcons.VerticalSplit, MiuixIcons.Contacts, MiuixIcons.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 ->
    // 内容区域需要考虑 padding
    Box(
        modifier = Modifier
            .fillMaxSize()
            .padding(paddingValues),
        contentAlignment = Alignment.Center
    ) {
        Text(
            text = "当前页面:${pages[selectedIndex]}",
            style = MiuixTheme.textStyles.title1
        )
    }
}

变更日志

基于 Apache-2.0 许可发布