Android 官方在 2016 年 3 月更新了 Bottom navigation 设计规范,所谓设计规范就是告诉开发者和设计师要如何去设计和使用某一个组件。不过这次 Bottom navigation 的发布,让许多人大跌眼镜,毕竟 Bottom navigation 这样的组件,在之前的 MD 设计语言中可是只字未提,当时 Android 与 iOS 常见的导航布局也有差异:iOS 应用常用底部标签栏,Android 的旧指南则建议避免这种布局。这是设计建议的变迁,不是两个平台的能力限制,也不是所有 iOS 应用都必须使用底栏。
本文是 Android Bottom navigation 的第二篇文章,主要介绍样式、行为与规格。
版本说明(2026-10-13 核查):本文主体保留 2016 年 Material Design 1(M1)的历史样式与图例,不是当前 Material 3(M3)的实现规范。现存 M1 官方归档与原图的部分数值已有差异,下文逐处注明。现代实现以 Compose Material3 1.3.0 的源码作明确版本参照,见第 5 节;该库版本不等于 Android 系统版本。
使用场景和窗口适配见第一篇。
1. 样式-Style
1.1 图标和文字-Icons and text
Because bottom navigation actions are presented as icons, they should be used for content that can be suitably communicated with icons.
由于底部导航操作显示为图标,应选择能表达目的地含义的图标。以下为 M1 的历史标签规则,focus 在这里指当前选中的目的地,不是键盘焦点或 TalkBack 焦点:
- 当 Item 是 focus 状态的时候,显示这个 Item View 的图标和文字。
- 当 bottom navigation 只有三个 Item 的时候,他们的图标和文字都应该被显示。
- 当 bottom navigation 有四个或者五个 Item 的时候,在非激活状态的时候只显示他们的图标即可。
1.2颜色
Tint the current bottom navigation action (including the icon and any text label present) with the app’s primary color
M1 建议用应用主色表示当前选中项,以下为旧配色示例。M3 采用主题颜色角色和选中指示器,不应直接照搬这组黑白/主色规则。


如果底部导航条已着色,将底部导航操作图标和文字设置为白色或黑色。


1.3文本标签
文本标签为导航图标提供简明的定义。以下 M1 图例强调避免难以辨认的换行、截断和缩小文字。现代实现还要检查翻译后的长标签、系统大字体和无障碍名称,不能为了复刻旧图而强行缩小字体。




2.操作
下面是 M1 行为建议的适用范围:
- 图标表示一个顶层目的地,而不是打开菜单或对话框的操作;“不能跳转至其他窗口”的原翻译过宽,原规范说的是 menus/dialogs。
- 点击已选中项可按产品约定回到该目的地顶部或刷新;组件不会自动替业务执行这些操作。
- 可以配置整条底栏随滚动隐藏/显示,不是每个图标都必须单独变化,也不是默认接上滚动监听。
- 旧规范不建议用内容区横滑来切换底栏目的地,并推荐目的地间淡入淡出。它不禁止当前页面里的轮播、内容分页或其他横向手势。
- 原规范另有 Back 不在底栏目的地间轮转的建议;现代 Back 行为应与实际导航栈一致,不能简单拦截系统返回或在切换时销毁整个 Android task。状态恢复见第一篇的 Navigation 2.4.0 说明。
3.空间
3.1确定底部导航栏
Fixed 指各项使用固定/等宽布局,不是指栏始终显示。旧公式“栏宽 ÷ 项目数”计算的是整个点击区域,不是图标本身;分配时还要满足最小/最大宽度,不能在宽屏上无限拉伸。

宽度的最大及最小值(这些数据包含边距):
- 最大值:168dp
- 最小值:现存 M1 归档为 80dp;原稿写较大界面 120dp、较小界面 104dp,其中仓库旧图标了 104dp。归档版本与旧图不同,不能把它们混成一个规范。

高度:
56dp
图标:
24*24dp

内容对齐:
图标在上、文字在下,整体水平居中;不是要求文字与图标并排。
边距:
- 图标上方 6dp(当前项)、8dp(未激活项)
- 文字下方 10dp
- 距文本左右各 12dp
文本标签:
- 常规 Roboto字体: 14sp(当前界面)
- 常规 Roboto字体:12sp(未激活界面)




3.2切换底部导航栏
这里的 Shifting 是选中项与未选中项宽度不同的旧布局,不是横向滚动底栏。不能继续套用“总宽 ÷ 项目数”给所有项等宽;旧规范分别约束两种状态。

宽度的最大及最小值(这些数据包含边距):
当前界面
- 最大值:168 dp
- 最小值:96 dp
未激活界面
- 最大值:96 dp
- 最小值:原图为 64dp,现存 M1 归档为 56dp;保留原图作为历史版本证据。




高度:
56dp
图标:
24*24 dp
内容对齐:
选中项图标在上、文字在下,水平居中;未选中项只显示图标时按旧布局居中。
边距:
- 距图标上 6dp(当前界面),距图标上下各 16dp(未被激活界面)
- 距文本下 10dp
文本标签:
常规 Roboto 字体: 14sp(当前界面)


4. 层级
M1 把 Snackbar 与底栏的概念 elevation 分别列为 6dp 和 8dp。这里的“后面”是层级关系,不表示 Snackbar 文本应被遮住;下图中的消息仍位于底栏上方并可读。现代布局不能只比较两个数值来决定位置或遮挡。
抽屉、模态底部面板和软键盘的显示关系由具体布局、窗口和 inset 处理共同决定。尤其 IME 属于系统窗口,不能概括为应用内一个“elevation 更高的 View”,也不保证总是完全盖住底栏。


5. 2026 年补充:以具体组件版本为准
下面核对的是 Google Maven 发布的 Compose Material3 1.3.0 源码包中的 NavigationBar.kt、NavigationBarTokens.kt 与 Scaffold.kt,不是把某个数值宣布为所有 M3 实现的固定值。
- 标签与宽度。 提供 label 时,
NavigationBarItem的alwaysShowLabel默认是true,不会因为有四或五项就自动隐藏非选中标签;源码给各项相同的 weight。不要将旧 shifting 样式当作这个组件的默认行为。 - 尺寸与颜色。 该版本普通
NavigationBar的容器最小高度 token 为 80dp、图标 token 为 24dp;可用约束、内容及 inset 会影响最终测量高度,不是把旧 56dp 换成一个新的硬编码总高度。默认选中图标使用onSecondaryContainer,指示器使用secondaryContainer,选中标签使用onSurface,跟随主题而非统一刷 primary。 - 系统区域。 组件默认处理底部和水平方向的 system-bar inset,不等于整个页面或 IME 已处理完。
Scaffold把内容避让量作为innerPadding交给调用方,内容仍需应用它,并按层级消费 inset,避免与手动 padding 重复。官方说明区分了两者的责任;键盘避让另见 IME/inset 用法。 - Snackbar。 放入
Scaffold.snackbarHost后,该版本会依据 bottomBar/FAB 的实际尺寸安排位置;不需要为了“层级够高”强行覆盖底栏。自定义容器则需自行验证消息和操作按钮都能看见、点到。 - 可访问性。 24dp 是图标尺寸,不是点击区域。检查至少 48dp 的触摸目标、可理解的名称、选中状态、字体放大与 RTL;不要在文字已表达名称时制造重复朗读。Compose 无障碍默认行为可作为检查依据。
应用内 Navigation bar、系统导航区域和键盘是三种不同对象;实现时分别确认它们的尺寸与避让责任。
关于我 && 博客
下面是个人的介绍和相关的链接,期望与同行的各位多多交流,三人行,则必有我师!
- 博主个人介绍 :里面有个人的微信和微信群链接。
- 本博客内容导航 :个人博客内容的一个导航。
- 个人整理和搜集的优秀博客文章 - Android 性能优化必知必会 :欢迎大家自荐和推荐 (微信私聊即可)
- Android性能优化知识星球:付费社群已于 2026 年停止运营,不再招收新成员;此处保留历史介绍。
一个人可以走的更快 , 一群人可以走的更远
