学而实习之 不亦乐乎

Android:底部导航栏 BottomNavigationView 用法

2022-01-05 13:02:22

一、概述

这是 material design 提供的一个标准底部导航栏的实现,可以轻松的实现导航栏菜单之间的切换与浏览。使用方式更加快捷方便,适用于拥有3-5个子菜单。

二、基本用法

1、添加引用菜单布局

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/navigation_homefirst"
        android:icon="@drawable/home1_shape"
        android:title="首页"/>

    <item
        android:id="@+id/navigation_homesecond"
        android:icon="@drawable/home2_shape"
        android:title="订单" />

    <item
        android:id="@+id/navigation_homethird"
        android:icon="@drawable/home3_shape"
        android:title="动态" />

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

</menu>

2、添加布局:

<?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:orientation="vertical"
    tools:context=".Demo2">

    <FrameLayout
        android:id="@+id/tb"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#fff"
        app:itemIconTint="@drawable/home_color_shape"
        app:itemTextColor="@drawable/home_color_shape"
        app:menu="@menu/navigation" />

</LinearLayout>

属性说明
itemBackground:设置导航栏的背景颜色
itemIconTint:设置导航栏中图片的颜色
itemTextColor:设置导航栏中文字的颜色

3、添加 Fragment 

这里只简单显示文字,列出其中一个,其他的相似。
如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".FirstFragment">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello_blank_fragment_1" />
</LinearLayout>

4、在 Activity 中使用

public class MainActivity extends AppCompatActivity {
    private BottomNavigationView navigation;
    private FirstFragment firstFragment;
    private SecondFragment secondFragment;
    private ThirdFragment thirdFragment;
    private FourthFragment fourthFragment;

    private Fragment[] fragments;
    //默认选择第一个fragment
    private int lastSelectedPosition = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_demo2);

        firstFragment = new FirstFragment();
        secondFragment = new SecondFragment();
        thirdFragment = new ThirdFragment();
        fourthFragment = new FourthFragment();

        fragments = new Fragment[]{firstFragment, secondFragment, thirdFragment,fourthFragment};

        navigation = this.findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener((item) -> {
            switch (item.getItemId()) {
                case R.id.navigation_homefirst:
                    if (0 != lastSelectedPosition) {
                        setDefaultFragment(lastSelectedPosition, 0);
                        lastSelectedPosition = 0;
                    }
                    return true;
                case R.id.navigation_homesecond:
                    if (1 != lastSelectedPosition) {
                        setDefaultFragment(lastSelectedPosition, 1);
                        lastSelectedPosition = 1;
                    }
                    return true;
                case R.id.navigation_homethird:
                    if (2 != lastSelectedPosition) {
                        setDefaultFragment(lastSelectedPosition, 2);
                        lastSelectedPosition = 2;
                    }
                    return true;
                case R.id.navigation_homefourth:
                    if (3 != lastSelectedPosition) {
                        setDefaultFragment(lastSelectedPosition, 3);
                        lastSelectedPosition = 3;
                    }
                    return true;
            }
            return false;
        });

    }

    /**
     * 切换Fragment
     * @param lastIndex 上个显示Fragment的索引
     * @param index     需要显示的Fragment的索引
     */
    private void setDefaultFragment(int lastIndex, int index) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.hide(fragments[lastIndex]);
        if (!fragments[index].isAdded()) {
            transaction.add(R.id.tb, fragments[index]);
        }
        // 需要展示fragment下标的位置
        // commit:安排该事务的提交。这一承诺不会立即发生;它将被安排在主线程上,以便在线程准备好的时候完成。
        // commitAllowingStateLoss:与 commit类似,但允许在活动状态保存后执行提交。这是危险的,因为如果Activity需要从其状态恢复,
        // 那么提交就会丢失,因此,只有在用户可以意外地更改UI状态的情况下,才可以使用该提交
        transaction.show(fragments[index]).commit();
    }
}