前两天写了一篇《我觉得,是时候该好好聊聊 Android Navigation 了。》博客,今天就接着把 Navigation + BottomNavigationView 的博客给续上吧。

《我觉得,是时候该好好聊聊 Android Navigation 了。》博客地址: https://bin.zmide.com/?p=967

博客中的代码都已经上传到 GitHub,感谢小伙伴们点亮的小星星,虽然还没点,但总不会还有人不想点亮小星星的吧。 https://github.com/PBK-B/android-use-navigation-demo

好了,正文开始,首先需要先导入 material 包,编辑 app/build.gradle 文件添加

……

dependencies {

    implementation 'com.google.android.material:material:1.4.0'
    
}

……

当然现在新建的项目基本都会默认带该包,接着基于上次的项目在 activity_main.xml 布局文件中添加 com.google.android.material.bottomnavigation.BottomNavigationView 组件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".ui.activity.MainActivity">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/a_main_nav_host"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@null" />


</LinearLayout>

接着,我们需要创建一个 menu 文件写入底部导航的图标和文本,但是在创建 menu 文件前我们需要先弄几张图标,这里由于我是 demo 项目就不找好看的了直接在 Google 提供的图标包中弄两个。

Android jetpack 使用篇,当 Navigation 遇上 BottomNavigationView-天真的小窝

Android jetpack 使用篇,当 Navigation 遇上 BottomNavigationView-天真的小窝
Android jetpack 使用篇,当 Navigation 遇上 BottomNavigationView-天真的小窝

选中 drawable 资源文件夹,选择 New 点击 Image Asset,打开之后将 icon type 设置为 Action Bar and Tab Icon 点击 Clip Art 选择你想要的图标修改名称就可以将图片加入到自己的资源文件夹中了。我添加了两张 i

c_action_nav_home (主页)

ic_action_nav_user (用户页面)

Android jetpack 使用篇,当 Navigation 遇上 BottomNavigationView-天真的小窝
Android jetpack 使用篇,当 Navigation 遇上 BottomNavigationView-天真的小窝
Android jetpack 使用篇,当 Navigation 遇上 BottomNavigationView-天真的小窝

接着选中 res 点击 New -> Android Resource File,输入文件名后选择 Resource type 类型为 Menu,创建成功后在资源目录会出现一个 menu/bottom_nav_menu.xml 文件,在文件的 menu 节点下添加 item 项。

item 项属性如下:

android:id 这里是绑定 navigation 的 nav_graph.xml 文件中页面绑定的 id 值

android:icon 这是显示的图标文件

android:title 图标下方的提示文本

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/homeFragment"
        android:icon="@drawable/ic_action_nav_home"
        android:title="主页" />

    <item
        android:id="@+id/userFragment"
        android:icon="@drawable/ic_action_nav_user"
        android:title="我的" />

</menu>


创建好 menu 文件后就可以在 activity_main.xml 布局文件中将 menu 设置给 BottomNavigationView 组件,并且给 BottomNavigationView 组件一个 id。

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/a_main_bottom_nav"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?android:attr/windowBackground"
    app:menu="@menu/bottom_nav_menu"/>

这样我们的布局就搞定了,接着我们绑定 Navigation 实现点击切换不同页面,通过 NavHostFragment 拿到 NavController 之后使用 NavigationUI.setupWithNavController() 方法就可以将 navigation 绑定到 BottomNavigationView 组件上了

private void initNav() {
        // 通过 getSupportFragmentManager 获取 NavHostFragment
        NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.a_main_nav_host);
        // 获取 NavController
        NavController navController = navHostFragment.getNavController();

        // 获取 BottomNavigationView
        BottomNavigationView bottomNavigationView = findViewById(R.id.a_main_bottom_nav);

        // 将底部导航绑定 Navigate
        NavigationUI.setupWithNavController(bottomNavigationView,navController);
}

现在简单的使用是基本实现了,但是这样不管跳转哪个页面都会出现这个底部导航,如果子页面不想显示底部导航该怎么弄呢?

可以通过添加 Navigate 跳转监听,如果参数不带 ShowAppBar 将不显示底部导航栏。具体代码如下

getNavController().addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
            @Override
            public void onDestinationChanged(@NonNull NavController navController, @NonNull NavDestination navDestination, @Nullable Bundle bundle) {
                if (bundle != null && bundle.getBoolean("ShowAppBar")) {
                    bottomNavigationView.setVisibility(View.VISIBLE);
                } else {
                    bottomNavigationView.setVisibility(View.GONE);
                }
            }
        });

然后给需要带底部导航的一个默认 ShowAppBar 为 true 的值就好了。navigation/nav_graph.xml 配置文件如下

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/homeFragment">

    <fragment
        android:id="@+id/homeFragment"
        android:name="com.pbkhub.smartcity.ui.fragment.HomeFragment"
        android:label="fragment_home"
        tools:layout="@layout/fragment_home" />

    <fragment
        android:id="@+id/userFragment"
        android:name="com.pbkhub.smartcity.ui.fragment.UserFragment"
        android:label="fragment_user"
        tools:layout="@layout/fragment_user" />

    <activity
        android:id="@+id/guideActivity"
        android:name="com.pbkhub.smartcity.ui.activity.GuideActivity"
        android:label="activity_guide"
        tools:layout="@layout/activity_guide" />


</navigation>

好了,到这里对于 BottomNavigationView 组件 + navigation 的基础使用方法就结束了,感谢看到现在的你,下次见。