天天看点

基于BottomNavigationView实现底部导航栏

预览

基于BottomNavigationView实现底部导航栏
  1. 新建三个对应于fragment的layout文件
    基于BottomNavigationView实现底部导航栏
代码如下(三个都一样,就不一一列出了)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="HomeFragment"
        android:textSize="18sp"
        android:textColor="@color/black"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
           
  1. 新建三个类继承与androidx.fragment.app包下的Fragment;(需要几个界面就新建几个这里只是演示)
    基于BottomNavigationView实现底部导航栏
  2. 在新建的三个Fragment中重写父类的onCreateView()方法,并绑定布局
三个类的代码也都相同,需要注意的是—>布局别绑定错了!
public class HomeFragment extends Fragment {
    private View mRootView;
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mRootView = inflater.inflate(R.layout.fragment_home,container,false);
        return mRootView;
    }
}
           
  1. 新建menu布局文件,用于BottomNavigationView
  • 新建menu包
    基于BottomNavigationView实现底部导航栏
    基于BottomNavigationView实现底部导航栏
  • 在menu包下新建布局文件
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/nav_home"
        android:title="首页"
        android:icon="@drawable/ic_baseline_home_24"/>
        <!--icon就是对应要显示的图标-->
    <item
        android:id="@+id/nav_news"
        android:title="新闻"
        android:icon="@drawable/ic_baseline_fiber_new_24"/>
    <item
        android:id="@+id/nav_personal"
        android:title="我的"
        android:icon="@drawable/ic_baseline_person_24"/>

</menu>
           
  1. 在宿主Activity的布局中添加
通过menu属性来完成绑定menu资源
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MainActivity">
    
    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        
        app:menu="@menu/bottom_navigation_menu"
        
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
           
  1. 宿主类MainActivity
/**
 * 宿主Activity
 */
public class MainActivity extends AppCompatActivity {
    private BottomNavigationView bottomNavigation;

    // 持有对应Fragment的对象
    private HomeFragment mHomeFragment;
    private NewsFragment mNewsFragment;
    private PersonalFragment mPersonalFragment;
    // 用于存放fragment的数组
    private Fragment[] mFragmentContainer;
    // 用于标记最后一个fragment的标签
    public int mLastFragmentTag;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        loadData();
        registerListener();
    }

	/**
     * 注册监听
     */
    private void registerListener() {
        // 给BottomNavigation设置监听以切换fragment
        bottomNavigation.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
            @SuppressLint("NonConstantResourceId")
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.nav_home:
                        if (mLastFragmentTag !=0) {
                            choseFragment(mLastFragmentTag,0);
                            mLastFragmentTag = 0;
                        }
                        // 监听事件中“return true”
                        // 表示这个按钮的监听事件在这个方法中已经处理完成了,不需要别人再去处理了
                        return true;
                    case R.id.nav_news:
                        if (mLastFragmentTag !=1) {
                            choseFragment(mLastFragmentTag,1);
                            mLastFragmentTag = 1;
                        }
                        return true;
                    case R.id.nav_personal:
                        if (mLastFragmentTag !=2) {
                            choseFragment(mLastFragmentTag,2);
                            mLastFragmentTag = 2;
                        }
                        return true;
                }
                return false;
            }
        });
    }

	/**
     * 用于切换到需要的显示Fragment
     * @param lastFragmentTag   lastFragmentTag
     * @param index             需要显示的Fragment的index
     *                          HomeFragment ---> 0
     *                          NewsFragment ---> 1
     *                          PersonalFragment ---> 2
     */
    private void choseFragment(int lastFragmentTag, int index) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        // 隐藏上一个Fragment
        transaction.hide(mFragmentContainer[lastFragmentTag]);
        // 如果新的Fragment的对象还在容器中,就不需要去new对象了,直接显示就好
        if (!mFragmentContainer[index].isAdded()) {
            transaction.add(R.id.fragment_container,mFragmentContainer[index]);
        }
        // commitNowAllowingStateLoss()允许在保存活动状态后执行提交
        transaction.show(mFragmentContainer[index]).commitNowAllowingStateLoss();
    }

	/**
     * 加载数据
     */
    private void loadData() {
        mHomeFragment = new HomeFragment();
        mNewsFragment = new NewsFragment();
        mPersonalFragment = new PersonalFragment();
        // 将初始化后的Fragment添加到容器中
        mFragmentContainer = new Fragment[]{mHomeFragment,mNewsFragment,mPersonalFragment};

        // 将进入应用默认显示的Fragment对应的tag值设置为0
        mLastFragmentTag = 0;
        // 默认显示为HomeFragment
        // 获取Fragment管理器并开始操作
        // 替换(第一个参数为容器【remove】,第二个参数为要放在容器中新的Fragment【add】)
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.fragment_container,mHomeFragment)
                .show(mHomeFragment)
                .commit();
    }

    private void initView() {
        bottomNavigation = findViewById(R.id.bottom_navigation);
    }
}