Android BottomNavigationView 入门介绍

文章目录

一、什么是 BNV

BottomNavigationView(简称 BNV) 是 Material Components 库提供的一个底部导航控件,固定在页面底部,用于在 3~5 个顶层页面之间快速切换,常见于「首页 / 视频 / 我的」这类 App 结构。

它自带图标 + 文字、选中态变色、点击涟漪反馈,开箱即用,是 Android 官方推荐的底部导航方案。

二、为什么用它

  • 符合 Material 规范:官方组件,样式统一,不用自己手写底部栏。
  • 省事:菜单、选中态、点击反馈都由组件内部处理,只需提供菜单资源。
  • 适合顶层导航:底部是拇指最容易触达的区域,适合放最常用的几个一级入口。

对比一下:TabLayout 一般放在顶部,适合配合 ViewPager2 做内容分页;BNV 放在底部,适合做 App 的全局一级导航。两者用途不同,有时也会一起使用。

三、引入依赖

Material 组件库(新建项目一般已默认带上):

groovy 复制代码
implementation 'com.google.android.material:material:1.12.0'

四、定义菜单

BNV 的每个 Tab 对应一个菜单项,先建 res/menu/bottom_main_menu.xml:

xml 复制代码
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/first_page"  android:title="首页" android:icon="@drawable/ic_home" />
    <item android:id="@+id/screen_page" android:title="视频" android:icon="@drawable/ic_screen" />
    <item android:id="@+id/song_page"   android:title="刷歌" android:icon="@drawable/ic_song" />
    <item android:id="@+id/star_page"   android:title="星光" android:icon="@drawable/ic_star" />
    <item android:id="@+id/my_page"     android:title="我的" android:icon="@drawable/ic_user" />
</menu>

菜单项建议控制在 3~5 个:少于 3 个没必要用底部栏,多于 5 个 Material 会退化成「更多」模式,体验变差。

五、布局中声明

xml 复制代码
<com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/bottom_navigation_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#FFFFFF"
    app:itemIconSize="20dp"
    app:itemIconTint="@color/item_color"
    app:itemTextColor="@color/item_color"
    app:itemRippleColor="@android:color/transparent"
    app:itemActiveIndicatorStyle="@null"
    app:labelVisibilityMode="labeled"
    app:menu="@menu/bottom_main_menu"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent" />

六、常用属性

属性 作用
app:menu 绑定菜单资源,决定有几个 Tab
app:itemIconSize 统一图标尺寸,避免菜单里图标大小不一
app:itemIconTint 图标着色,传 ColorStateList 实现选中变色
app:itemTextColor 文字着色,同样用 ColorStateList
app:itemActiveIndicatorStyle Material3 的选中胶囊背景,传 @null 可去掉
app:itemRippleColor 点击涟漪颜色,传透明可禁用
app:labelVisibilityMode labeled / unlabeled / selected / auto

选中 / 未选中变色,res/color/item_color.xml:

xml 复制代码
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="#000000" android:state_selected="true"/>
    <item android:color="#AAAAAA" android:state_selected="false"/>
</selector>

七、点击事件

java 复制代码
bnv.setOnItemSelectedListener(item -> {
    int id = item.getItemId();
    if (id == R.id.first_page) {
        switchTo(R.id.first_page);
        return true;   // 返回 true 表示已消费该事件,Tab 会保持选中
    }
    return false;
});

八、配合 Fragment 切换页面

点击 Tab 后一般用 FragmentManager 切换页面。推荐缓存实例,避免每次点击都重新创建 Fragment:

java 复制代码
private final HashMap<Integer, Fragment> pages = new HashMap<>();
private Fragment currentFragment;

private void switchTo(int tabId) {
    Fragment target = pages.get(tabId);
    if (target == null) {
        if (tabId == R.id.first_page) {
            target = new HomeFragment();
        } else {
            return;   // 还没做的页面先忽略
        }
        pages.put(tabId, target);
    }
    if (target == currentFragment) return;

    getSupportFragmentManager().beginTransaction()
            .replace(R.id.fragment_container, target)
            .commit();
    currentFragment = target;
}

用 HashMap 缓存后,切回某个 Tab 时页面里的滚动位置、列表状态都能保留,不会每次被重置。

九、和 ViewPager2 联动

如果每个 Tab 的内容需要横向滑动切换,可以让 BNV 和 ViewPager2 双向联动:

java 复制代码
// ViewPager2 滑动时同步选中 BNV 的 Tab
viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
    @Override
    public void onPageSelected(int position) {
        bnv.getMenu().getItem(position).setChecked(true);
    }
});

// 点击 BNV 时让 ViewPager2 滚过去
bnv.setOnItemSelectedListener(item -> {
    int index = /* 菜单项对应的下标 */;
    viewPager.setCurrentItem(index, false);
    return true;
});

这种方式适合页面较少、且切换有明显左右滑动语义的场景。

十、常见问题

  1. Material3 多了一个灰色胶囊背景 加 app:itemActiveIndicatorStyle="@null" 去掉。

  2. 各 Tab 图标大小不一致 菜单里的矢量图 viewport 可能不同,用 app:itemIconSize 统一强制尺寸。

  3. 点击后 Tab 又跳回原来那个 setOnItemSelectedListener 里记得对已处理的项 return true。

十一、小结

  • 菜单控制在 3~5 项,保持顶层结构清晰;
  • 用 ColorStateList 统一选中 / 未选中配色;
  • 切换页面建议缓存 Fragment 实例,避免状态丢失;
  • 需要横向滑动时再考虑和 ViewPager2 联动;
  • 注意沉浸式布局下给底部留出系统导航栏高度。

BNV 本身开箱即用,把这些细节做好,底部导航就从「能用」变成「好用」了。

相关推荐
三少爷的鞋3 小时前
AI 时代,我们都将成为通才型开发者:只懂 Android,已经不够了
android
Dovis(誓平步青云)7 小时前
家里设备越来越多,如何用一张空间地图控制灯光和温度![
android·java·前端·javascript·人工智能·电脑
晚风叙码8 小时前
MySQL 数据类型详解:从数值到字符串,一篇讲透
android·mysql·adb
传奇开心果编程9 小时前
【Compose Multiplatform 跨端开发学与练】第3课 布局与组件
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程12 小时前
【Compose Multiplatform 跨端开发学与练】第8课 资源管理与主题
android·windows·学习·ios·kotlin·web·composer
传奇开心果编程13 小时前
【Compose Multiplatform 跨端开发学与练】第9课 测试与调试
android·学习·macos·ios·kotlin·web·composer
传奇开心果编程13 小时前
【Compose Multiplatform 跨端开发学与练】第4课 导航与路由
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程14 小时前
【Compose Multiplatform 跨端开发学与练】第6课 状态管理与架构
android·学习·ui·ios·架构·kotlin·composer
事圆则缓14 小时前
Android AOSP 定制常见概念:源码目录、系统镜像与刷机流程
android
传奇开心果编程14 小时前
【Compose Multiplatform 跨端开发学与练】第2课 Compose 基础语法
android·windows·学习·ui·ios·kotlin·composer