Android ViewPager2 + Fragment + BottomNavigationView 联动
Android ViewPager2 + Fragment + BottomNavigationView 联动
本篇主要介绍一下 ViewPager2 + Fragment + BottomNavigationView , 上篇中把ViewPager2和Fragment 联动起来了, 本篇主要把 BottomNavigationView集成进去

概述
BottomNavigationView 是一个底部导航控件, 现在要实现的效果就是 滑动ViewPager2 中的Fragment 并且底部BottomNavigationView 菜单部分跟着联动 同理反过来 点击BottomNavigationView 的时候 ViewPager2中的Fragment 也对应滑动, 下面来看看如何实现的吧
实现思路
1.Activity 布局文件中引入 ViewPager2 控件
2.编写menu文件 提供给BottomNavigationView 用于展示
3.Activity 布局文件中引入BottomNavigationView 控件
4.编写 Fragment 用于填充到ViewPager2中
5.编写Adapter 实现 FragmentStateAdapter
6.BottomNavigationView添加 setOnItemSelectedListener 联动ViewPager2
7.ViewPager2 添加 registerOnPageChangeCallback 联动 BottomNavigationView
代码实现
下面就来按照上面的思路一步步实现代码啦!
1.Activity 布局文件中引入 ViewPager2 控件
<?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=".ViewPager2BottomActivity">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager2bottom"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/bootomnav2"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
2.编写menu文件 提供给BottomNavigationView 用于展示
图标icon 自己配置吧
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:title="首页"
android:id="@+id/home_item"
android:icon="@drawable/ic_baseline_home_24"
/>
<item
android:title="类型"
android:id="@+id/type_item"
android:icon="@drawable/ic_baseline_merge_type_24"
/>
<item
android:title="添加"
android:id="@+id/add_item"
android:icon="@drawable/ic_baseline_add_24"
/>
<item
android:title="设置"
android:id="@+id/setting_item"
android:icon="@drawable/ic_baseline_settings_24"
/>
</menu>
3.Activity 布局文件中引入BottomNavigationView 控件
package com.johnny.slzzing;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.w3c.dom.Text;
/**
* A simple {@link Fragment} subclass.
* Use the {@link Bottom2Fragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class Bottom2Fragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
public Bottom2Fragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment Bottom2Fragment.
*/
// TODO: Rename and change types and number of parameters
public static Bottom2Fragment newInstance(String param1, String param2) {
Bottom2Fragment fragment = new Bottom2Fragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_bottom2, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
TextView textView = view.findViewById(R.id.textview2);
//把动态传入的参数设置到 textView上
textView.setText(mParam1);
}
}
fragment_bottom2.xml
<?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=".ViewPager2BottomActivity">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager2bottom"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/bootomnav2"
/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bootomnav2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/viewpager2bottom"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/bottom_item_menu"
app:labelVisibilityMode="labeled"
/>
<!-- 这个要设置 app:labelVisibilityMode="labeled" 才能显示图标文字 因为我这里超过了3个-->
</androidx.constraintlayout.widget.ConstraintLayout>
4.编写 Fragment 用于填充到ViewPager2中
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".Bottom2Fragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="@+id/textview2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:gravity="center"
android:textSize="25sp"
android:textStyle="bold"
android:textColor="@color/black"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
5.编写Adapter 实现 FragmentStateAdapter
上篇已经说过了 直接继承 FragmentStateAdapter
class MyViewPager2BottomAdapter extends FragmentStateAdapter {
List<Fragment> fragmentList;
public MyViewPager2BottomAdapter(@NonNull FragmentActivity fragmentActivity, List<Fragment> list) {
super(fragmentActivity);
this.fragmentList = list;
}
@NonNull
@Override
public Fragment createFragment(int position) {
return fragmentList.get(position);
}
@Override
public int getItemCount() {
return fragmentList.size();
}
}
6.BottomNavigationView添加 setOnItemSelectedListener 联动ViewPager2
bottomNavigationView.setOnItemSelectedListener核心方法
Acitivity 中实现如下代码:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_pager2_bottom);
viewPager2 = findViewById(R.id.viewpager2bottom);
bottomNavigationView = findViewById(R.id.bootomnav2);
MyViewPager2BottomAdapter myViewPager2BottomAdapter =
new MyViewPager2BottomAdapter(this,initFragmentList());
viewPager2.setAdapter(myViewPager2BottomAdapter);
//重点 设置 bottomNavigationView 的item 的点击事件 设置viewPager2的联动
bottomNavigationView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
int itemId = item.getItemId();
switch (itemId){
case R.id.home_item:
viewPager2.setCurrentItem(0);
break;
case R.id.type_item:
viewPager2.setCurrentItem(1);
break;
case R.id.add_item:
viewPager2.setCurrentItem(2);
break;
case R.id.setting_item:
viewPager2.setCurrentItem(3);
break;
}
return true;
}
});
}
7.ViewPager2 添加 registerOnPageChangeCallback 联动 BottomNavigationView
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_pager2_bottom);
viewPager2 = findViewById(R.id.viewpager2bottom);
bottomNavigationView = findViewById(R.id.bootomnav2);
MyViewPager2BottomAdapter myViewPager2BottomAdapter =
new MyViewPager2BottomAdapter(this,initFragmentList());
viewPager2.setAdapter(myViewPager2BottomAdapter);
bottomNavigationView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
int itemId = item.getItemId();
switch (itemId){
case R.id.home_item:
viewPager2.setCurrentItem(0);
break;
case R.id.type_item:
viewPager2.setCurrentItem(1);
break;
case R.id.add_item:
viewPager2.setCurrentItem(2);
break;
case R.id.setting_item:
viewPager2.setCurrentItem(3);
break;
}
return true;
}
});
//重点 实现滑动的时候 联动 bottomNavigationView的selectedItem
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
switch (position){
case 0:
bottomNavigationView.setSelectedItemId(R.id.home_item);
break;
case 1:
bottomNavigationView.setSelectedItemId(R.id.type_item);
break;
case 2:
bottomNavigationView.setSelectedItemId(R.id.add_item);
break;
case 3:
bottomNavigationView.setSelectedItemId(R.id.setting_item);
break;
}
}
});
}

总结
本篇主要介绍了 如何把ViewPager2 + Fragment + BottomNavigationView 集成起来并且实现ViewPager2和BottomNavigationView的双向联动
ViewPager和ViewPager2 一些区别:
- ViewPager 的 Adapter 继承 FragmentStatePagerAdapter 而 ViewPager2 的Adapter 继承 FragmentStateAdapter
- ViewPager 滑动监听是 viewPager.addOnPageChangeListener方法 而ViewPager2 滑动监听是 registerOnPageChangeCallback 方法
欢迎大家访问 个人博客 Johnny小屋
欢迎关注个人公众号

Android ViewPager2 + Fragment + BottomNavigationView 联动的更多相关文章
- Android 底部按钮BottomNavigationView + Fragment 的使用(二)
这里来试验BottomNavigationView + Fragment 底部按钮通过点击底部选项,实现中间的Fragment进行页面的切换. 使用BottomNavigationView 控件,实现 ...
- Android 底部按钮BottomNavigationView + Fragment + viewPager 的使用(一)
实现的效果,左右滑动,底部栏跟着滑动,中间加的是分帧的页面 上代码:主页面activity_main.xml <?xml version="1.0" encod ...
- Android:Activity+Fragment及它们之间的数据交换.
Android:Activity+Fragment及它们之间的数据交换 关于Fragment与Fragment.Activity通信的四种方式 比较好一点的Activity+Fragment及它们之间 ...
- Android中Fragment和ViewPager那点事儿(仿微信APP)
在之前的博文<Android中使用ViewPager实现屏幕页面切换和引导页效果实现>和<Android中Fragment的两种创建方式>以及<Android中Fragm ...
- Android中Fragment与Activity之间的交互(两种实现方式)
(未给Fragment的布局设置BackGound) 之前关于Android中Fragment的概念以及创建方式,我专门写了一篇博文<Android中Fragment的两种创建方式>,就如 ...
- Android中Fragment的两种创建方式
fragment是Activity中用户界面的一个行为或者是一部分.你可以在一个单独的Activity上把多个Fragment组合成为一个多区域的UI,并且可以在多个Activity中再使用.你可以认 ...
- android之Fragment基础详解(一)
一.Fragment的设计哲学 Android在3.0中引入了fragments的概念,主要目的是用在大屏幕设备上--例如平板电脑上,支持更加动态和灵活的UI设计.平板电脑的屏幕比手机的大得多,有 ...
- Android使用Fragment来实现ViewPager的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
以下内容为原创,转载请注明:http://www.cnblogs.com/tiantianbyconan/p/3364728.html 我前两天写过一篇博客<Android使用Fragment来 ...
- android之fragment的使用
android中的fragment与html中的div很类似,下图中通过左边的按键可以控制右边的显示内容.右边的内容就是一个fragment,通过点击按键来控制fragment的实现. 工程目录 需要 ...
- Android使用Fragment定义弹出数字键盘
fragment主布局文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmln ...
随机推荐
- jmeter性能测试之正则提取响应头或者响应体
准备工作做好,先发送请求 然后察看结果树中的响应消息 比如我们要提取这个cookie,先调试一下,看能不能提取到 看蓝色的线条,我们提取到了,然后我们把这句话写入到后置处理器中的正则表达式提取里 再次 ...
- K8S容器HeadlessService间动态IP通信
文件网址:https://www.kubebiz.com/KubeBiz/MongoDB?k8sv=v1.20 使用文件网址中提供的yaml文件安装三节点的mongodb集群,其service是hea ...
- CentOS7.X yum安装MySQL8.0 数据表不区分大小写切换默认存储路径
查看当前系统版本的详细信息 # cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) yum源下载 地址:https://dev.m ...
- SpringBoot(七) - Redis 缓存
1.五大基本数据类型和操作 1.1 字符串-string 命令 说明 set key value 如果key还没有,那就可以添加,如果key已经存在了,那会覆盖原有key的值 get key 如果ke ...
- API接口笔记
1.基类 定义返回信息 protected $user; //用户表 protected $token; //用户token protected $isSuccess = FALSE; //状态是 ...
- JavaScript基础&实战(5)js中的数组、forEach遍历、Date对象、Math、String对象
文章目录 1.工厂方法创建对象 1.1 代码块 1.2.测试结果 2.原型对象 2.1 代码 2.2 测试结果 3.toString 3.1 代码 3.2 测试结果 4.数组 4.1 代码 5.字面量 ...
- 齐博x1换服务器如何转移网站?
如果你要把网站从本机传到服务器,又或者要更换服务器,请按下面的操作处理 第一步,必须要在原网站后台备份数据. 第二步,把备份好的网站所有文件,传到新服务器或空间 特别要注意 \cache\ 目录下建议 ...
- LINQ使用小贴士
LINQ中的排序操作符 OrderBy:按升序对序列的元素进行排序.OrderByDescending:按降序对序列的元素排序.ThenBy:按升序对序列中的元素执行后续排序.ThenByDescen ...
- Linux文件属性与管理
文件或目录属性主要包括: 索引节点,inode 文件类型 文件权限 硬链接个数 归属的用户和用户组 最新修改时间 查看命令 ls -lhi /opt 图解: Inode索引节点号,(人的身份证,家庭地 ...
- MySQL InnooDB引擎之并发事务问题以及隔离级别的作用和区别
最近在复习MySQL事务,但网上很多博客和资料可以说讲的不是模棱两可就是只有文字描述不够形象易懂,下面通过我的学习来详细讲一讲事务并发都会引起哪些问题?以及隔离级别是什么?InnoDB引擎是如何通过隔 ...