【Android】底部导航栏【BottomNavigationView】+【ViewPage2】

问题需求

实现底部导航栏切换
【Android】底部导航栏【BottomNavigationView】+【ViewPage2】_第1张图片

问题解决

最简单的实现方式就是使用系统自动生成的模板页面,但是有时候会有一些问题,特别是需要去除【ActionBar】的情况下,这种情况下使用系统的模板页面就不好用了,此时可以使用下面这种解决方式。

【BottomNavigationView】+【ViewPage2】
1.在res目录下创建【menu】目录,下面创建文件【bottom_nav_menu】

【Android】底部导航栏【BottomNavigationView】+【ViewPage2】_第2张图片

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

    <item
        android:id="@+id/navigation_home"
        android:icon="@drawable/bottom_home_select"
        android:title="预览" />

    <item
        android:id="@+id/navigation_statistics"
        android:icon="@drawable/bottom_statis_select"
        android:title="统计" />

    <item
        android:id="@+id/navigation_notifications"
        android:icon="@drawable/bottom_notif_select"
        android:title="通知" />

    <item android:id="@+id/navigation_myset"
        android:icon="@drawable/bottom_myset_select"
        android:title="设置"/>
</menu>
2.设置自定义导航图标切换显示效果

本文中需要显示四个图标,所以需要做四个选择切换背景
【Android】底部导航栏【BottomNavigationView】+【ViewPage2】_第3张图片
其中这四个切换背景设置是一样的,这里就贴一个出来
【bottom_home_select】的代码

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_home_select" android:state_selected="true" />
    <item android:drawable="@drawable/ic_home" android:state_selected="false" />
</selector>

然后这些切换效果添加在第一步中的【bottom_nav_menu】代码中

3.自定义文字切换颜色效果

一般来说,文字切换效果的颜色是和图标颜色切换颜色是对应的
【Android】底部导航栏【BottomNavigationView】+【ViewPage2】_第4张图片
这个【color】一般是需要我们自己创建文件夹,在文件夹中创建文件【nav_bottom_txt_select】
代码展示

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="#4878E3" android:state_selected="true" />
    <item android:color="#B6B6B6" android:state_selected="false" />
</selector>
4.依赖导入

【BottomNavigationView】是Android Studio自带就有,但是【ViewPage2】需要我们进行依赖导入,而【ViewPage2】又依赖【Recyclerview】,所以需要导入这两个依赖。

implementation 'androidx.viewpager2:viewpager2:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
5.【Activity】页面布局
<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/nav_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="0dp"
        android:layout_marginEnd="0dp"
        android:background="#ffffff"
        //导航页面底部文字选择切换效果
        app:itemTextColor="@color/nav_bottom_txt_select"
        //文字显示模式(下面讲述)
        app:labelVisibilityMode="labeled"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        //添加我们前面设置的menu
        app:menu="@menu/bottom_nav_menu" />

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/nav_viewpage2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toTopOf="@id/nav_view"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
6.【Fragment】页面创建

我们底部栏有四个按钮,所以我们需要创建四个【Fragment】,所以我们这边会有四个【Fragment】页面,再次不再叙述。
【Android】底部导航栏【BottomNavigationView】+【ViewPage2】_第5张图片
创建四个【Fragment】页面,分别命名【HomeFragment】、【StatisticsFragment】、【NotificationsFragment】、【MySetFragment】(里面什么都没有,就是一个空页面)。

7.创建ViewPage2的适配器

因为ViewPage2是依赖RecyclerView实现的,所以需要像使用Recyclerview一样创建一个适配器
【Java】版本

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import java.util.List;

/**
 * 作者 ldd
 * 日期 2023/2/7
 */
public class ViewPageAdapter extends FragmentStateAdapter {

    private List<Fragment> list;

    public ViewPageAdapter(@NonNull FragmentActivity fragmentActivity,
     List<Fragment> fragmentList) {
        super(fragmentActivity);
        list = fragmentList;
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        return list.get(position);
    }

    @Override
    public int getItemCount() {
        return list.size();
    }
}

【Kotlin】版本

import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter

/**
 * 作者 ldd
 * 日期 2023/2/7
 */
open class ViewPager2Adapter(
    fa: FragmentActivity,
    private val list: MutableList<Fragment>
) : FragmentStateAdapter(fa) {

    override fun getItemCount(): Int {
        return list.size
    }

    override fun createFragment(position: Int): Fragment {
        return list[position]
    }
    
}

下面使用的是【Kotlin】版本的

8.【Activity】代码

首先要去除系统主题的颜色,换成我们自定义的

//去除自带的选中颜色,去除后文字和图片选择效果就是跟我们自定义的效果一样
binding.navView.itemIconTintList = null
//将所有的【Fragment】添加到【ViewPager2】中
val fragmentList: MutableList<Fragment> = ArrayList()
fragmentList.add(HomeFragment())
fragmentList.add(StatisticsFragment())
fragmentList.add(NotificationsFragment())
fragmentList.add(MySetFragment())
binding.navViewpage2.adapter = ViewPager2Adapter(this, fragmentList)

//当viewpage2页面切换时nav导航图标也跟着切换
binding.navViewpage2.registerOnPageChangeCallback(object :
    ViewPager2.OnPageChangeCallback() {
    override fun onPageSelected(position: Int) {
       super.onPageSelected(position)
       binding.navView.menu.getItem(position).isChecked = true
    }
})

//当nav导航点击切换时,viewpager2也跟着切换页面
binding.navView.setOnItemSelectedListener { item ->
     when (item.itemId) {
         R.id.navigation_home -> {
            binding.navViewpage2.currentItem = 0
            return@setOnItemSelectedListener true
         }
         R.id.navigation_statistics -> {
            binding.navViewpage2.currentItem = 1
            return@setOnItemSelectedListener true
         }
         R.id.navigation_notifications -> {
            binding.navViewpage2.currentItem = 2
            return@setOnItemSelectedListener true
         }
         R.id.navigation_myset -> {
             binding.navViewpage2.currentItem = 3
             return@setOnItemSelectedListener true
         }
    }
    false
}

此时底部导航栏已经实现。

追加

在设置bottomNavigationView的布局文件时,有个属性【labelVisibilityMode】
此属性有四个值
【Android】底部导航栏【BottomNavigationView】+【ViewPage2】_第6张图片
显示效果
【Android】底部导航栏【BottomNavigationView】+【ViewPage2】_第7张图片

小红点(角标)

【BottomNavigationView】自带此功能
当设置

var bride = binding.navView.getOrCreateBadge(R.id.navigation_notifications)

【Android】底部导航栏【BottomNavigationView】+【ViewPage2】_第8张图片

此时导航栏对应的item位置会显示小红点
如果给bride设置一个值

 bride.number = 15

【Android】底部导航栏【BottomNavigationView】+【ViewPage2】_第9张图片

属性

backgroundColor :设置角标背景色
badgeGravity :设置角标的显示位置
TOP_START,
TOP_END,
BOTTOM_START,
BOTTOM_END

badgeTextColor:设置角标显示的数字颜色
maxCharacterCount:最多显示几位数字
如果设置为2,number设置为15
【Android】底部导航栏【BottomNavigationView】+【ViewPage2】_第10张图片

你可能感兴趣的:(Android学习笔记,android,java,开发语言)