之前早有耳闻 Google 为我们提供新的控件来替换老旧的 ViewPager 进而解决一些不好解决的bug问题,巴拉巴拉一大堆,就是前因后果啥的…相信读者已经在“张鸿洋”大神、“郭霖”大神或者是其他Android 大佬的公众号那里看见了许许多多了,或许各位感觉很无聊了,笔者菜鸟,分析不了历史背景,也不是很懂源码,但是小菜鸟,可以带给位看官尝个鲜,教你怎么用,怎么上手哈,闲话不多说,我们步入正题。

一、效果

二、介绍必要基础知识

1、ViewPager 与 ViewPager2 部分对比
ViewPager ViewPager 2
PagerAdapter RecyclerView.Adapter
FragmentStatePagerAdapter FragmentStateAdapter
addPageChangeListener registerOnPageChangeCallback
从右到左 (RTL) 的布局支持
垂直方向支持
停用用户输入的功能(setUserInputEnabled、isUserInputEnabled)
2、部分基础知识

ViewPager 2 底层是用 RecycleView 实现

三、撰写功能

1、依赖引入

implementation 'androidx.viewpager2:viewpager2:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0' // ViewPager 2 需要使用 RecycleView 的 adapter

2、实现横向滑动效果

1)、实现效果

2)、代码实现

a、 布局

Activity 布局内 就一个 ViewPager 2控件
item 界面就一个textView
就不展示了

b、逻辑
package com.example.viewpager2.horizontal;import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;import com.example.viewpager2.R;import java.util.ArrayList;
import java.util.List;/*** CreateTime: 2020/1/15 15:06* Author: hxd* Content:* UpdateTime:* UpdateName;* UpdateContent:*/
public class HorizontalVpAdapter extends RecyclerView.Adapter<HorizontalVpAdapter.HorizontalVpViewHolder> {private List<Integer> backgrounds;private Context mContext;HorizontalVpAdapter(Context context) {mContext = context;if (backgrounds == null) {backgrounds = new ArrayList<>();backgrounds.add(android.R.color.holo_blue_bright);backgrounds.add(android.R.color.holo_red_dark);backgrounds.add(android.R.color.holo_green_dark);backgrounds.add(android.R.color.holo_orange_light);backgrounds.add(android.R.color.holo_purple);}}@NonNull@Overridepublic HorizontalVpViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {return new HorizontalVpViewHolder(LayoutInflater.from(mContext).inflate((R.layout.item_h_v), parent, false));}@SuppressLint("SetTextI18n")@Overridepublic void onBindViewHolder(@NonNull HorizontalVpViewHolder holder, int position) {holder.mTextView.setText("第  " + (position + 1) + " 界面");holder.mLinearLayout.setBackgroundResource(backgrounds.get(position));}@Overridepublic int getItemCount() {if (backgrounds == null) {return 0;}return backgrounds.size();}class HorizontalVpViewHolder extends RecyclerView.ViewHolder {LinearLayout mLinearLayout;TextView mTextView;HorizontalVpViewHolder(@NonNull View itemView) {super(itemView);mLinearLayout = itemView.findViewById(R.id.ll_h_v);mTextView = itemView.findViewById(R.id.tv_hv);}}
}

适配器逻辑如上,因为 ViewPager 2 底层使用 RecycleView 实现的,所以这里不再使用 PagerAdapter 而是使用了 RecyclerView.Adapter 这也是 引入RecycleView 依赖的原因所在。

public class HorizontalActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_horizontal);ViewPager2 viewPager2 = findViewById(R.id.vp_h);HorizontalVpAdapter adapter = new HorizontalVpAdapter(this);viewPager2.setAdapter(adapter);}
}

Activity 内的代码就没什么不同了和之前一样的两步走,初始化控件,设置适配器。

3、纵向滑动效果

1)、实现效果

2)、代码逻辑

a、 布局

Activity 的布局需要拿出

    <androidx.viewpager2.widget.ViewPager2android:id="@+id/vp_v"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" />

布局内的 android:orientation="vertical" 控制横向和纵向滑动 有点类似于 LinearLayout

b、 逻辑
public class VerticalActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_vertical);ViewPager2 viewPager2 = findViewById(R.id.vp_v);VerticalVpAdapter adapter = new VerticalVpAdapter(this);viewPager2.setAdapter(adapter);viewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);}
}

Activity 内的viewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);可以实现 xml 内的android:orientation="vertical"相同效果。

4、RadioGroup 与 ViewPager 2 连用

1)、实现效果

2)、代码逻辑

a、 布局

Activity 布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"tools:context=".withRadioGroup.RgActivity"><androidx.viewpager2.widget.ViewPager2android:id="@+id/vp_rg"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_above="@+id/rg_vp" /><RadioGroupandroid:id="@+id/rg_vp"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_gravity="bottom"android:orientation="horizontal"><RadioButtonandroid:id="@+id/rb_home"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:button="@null"android:checked="true"android:drawableTop="@drawable/selector_home"android:drawablePadding="5dp"android:gravity="center"android:paddingTop="5dp"android:paddingBottom="5dp"android:text="@string/home"android:textColor="@color/selector_rg"android:textSize="16sp" /><RadioButtonandroid:id="@+id/rb_msg"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:button="@null"android:drawableTop="@drawable/selector_msg"android:drawablePadding="5dp"android:gravity="center"android:paddingTop="5dp"android:paddingBottom="5dp"android:text="@string/msg"android:textColor="@color/selector_rg"android:textSize="16sp" /><RadioButtonandroid:id="@+id/rg_my"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:button="@null"android:drawableTop="@drawable/selector_my"android:drawablePadding="5dp"android:gravity="center"android:paddingTop="5dp"android:paddingBottom="5dp"android:text="@string/my"android:textColor="@color/selector_rg"android:textSize="16sp" /></RadioGroup>
</RelativeLayout>

这里没啥说的就类似于各位 HomeActivity 的实现方式了。
每个 Fragment 内的布局更加简洁这里不再陈述

b、 逻辑

Adapter 内逻辑

package com.example.viewpager2.withRadioGroup;import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;import java.util.ArrayList;
import java.util.List;/*** CreateTime: 2020/1/15 16:32* Author: hxd* Content:* UpdateTime:* UpdateName;* UpdateContent:*/
public class RgAdapter extends FragmentStateAdapter {private List<Class> fragments;public RgAdapter(@NonNull FragmentActivity fragmentActivity) {super(fragmentActivity);if (fragments == null) {fragments = new ArrayList<>();}}public void addFragment(Fragment fragment) {if (fragments != null) {fragments.add(fragment.getClass());}}@NonNull@Overridepublic Fragment createFragment(int position) {try {return (Fragment) fragments.get(position).newInstance();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();}return null;}@Overridepublic int getItemCount() {return fragments.size();}
}

Activity 内代码

package com.example.viewpager2.withRadioGroup;import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;import android.os.Bundle;
import android.widget.RadioButton;
import android.widget.RadioGroup;import com.example.viewpager2.R;public class RgActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener {private ViewPager2 vpRg;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_rg);RgAdapter adapter = new RgAdapter(this);RadioGroup rgVp = findViewById(R.id.rg_vp);vpRg = findViewById(R.id.vp_rg);rgVp.setOnCheckedChangeListener(this);vpRg.setAdapter(adapter);adapter.addFragment(new HomeFragment());adapter.addFragment(new MessageFragment());adapter.addFragment(new MyFragment());vpRg.setCurrentItem(0);vpRg.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {@Overridepublic void onPageSelected(int position) {super.onPageSelected(position);switch (position) {case 0:((RadioButton) findViewById(R.id.rb_home)).setChecked(true);break;case 1:((RadioButton) findViewById(R.id.rb_msg)).setChecked(true);break;case 2:((RadioButton) findViewById(R.id.rg_my)).setChecked(true);break;}}});}@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {switch (checkedId) {case R.id.rb_home:vpRg.setCurrentItem(0);break;case R.id.rb_msg:vpRg.setCurrentItem(1);break;case R.id.rg_my:vpRg.setCurrentItem(2);break;}}
}

这里需要说的是 registerOnPageChangeCallback 方法 ,这个方法可以可以监听到 ViewPager 2 的界面变化,进而去操作其他的控件。

4、TabLayout 与 ViewPager 2 连用

1)、实现效果

2)、代码逻辑

a、 布局

Activity 布局

<?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"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><com.google.android.material.tabs.TabLayoutandroid:id="@+id/tb_vp"android:layout_width="match_parent"android:layout_height="wrap_content"app:tabIndicatorFullWidth="false"app:tabMode="scrollable"app:tabIndicatorColor="#0371DD"app:tabRippleColor="@android:color/transparent"app:tabSelectedTextColor="#0371DD"app:tabTextColor="#111111" /><androidx.viewpager2.widget.ViewPager2android:id="@+id/vp_tb"android:layout_width="match_parent"android:layout_height="match_parent" />
</LinearLayout>

Fragment 内布局很简单,不再列举了。

b、 逻辑

adapt 内部代码

package com.example.viewpager2.withTab;import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;import java.util.ArrayList;
import java.util.List;/*** CreateTime: 2020/1/15 17:47* Author: hxd* Content:* UpdateTime:* UpdateName;* UpdateContent:*/
public class TabAdapter extends FragmentStateAdapter {private List<Integer> colors;TabAdapter(@NonNull FragmentActivity fragmentActivity) {super(fragmentActivity);if (colors == null) {colors = new ArrayList<>();}}void addColor(int color) {if (colors != null) {colors.add(color);}}@NonNull@Overridepublic Fragment createFragment(int position) {return ShowFragment.newInstance(colors, position);}@Overridepublic int getItemCount() {return colors.size();}
}

这里提出一点,笔者 在 RadioGroup 、TabLayout 分别于ViewPager 2 的连用过程中分别使用了两种方法 将 Fragment 传给 adapter 这样的操作可以让各位的 Leaks 分析工具报出 内存泄漏。

Fragment 内的代码

package com.example.viewpager2.withTab;import android.annotation.SuppressLint;
import android.os.Bundle;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;import android.os.Parcelable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;import com.example.viewpager2.R;import java.util.ArrayList;
import java.util.List;public class ShowFragment extends Fragment {@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {return inflater.inflate(R.layout.fragment_show, container, false);}static ShowFragment newInstance(List<Integer> colors, int item) {Bundle bundle = new Bundle();bundle.putSerializable("color", (ArrayList<Integer>) colors);bundle.putInt("item", item);ShowFragment fragment = new ShowFragment();fragment.setArguments(bundle);return fragment;}@SuppressLint("SetTextI18n")@Overridepublic void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {view.<FrameLayout>findViewById(R.id.fl_show).setBackgroundResource(((ArrayList<Integer>) getArguments().getSerializable("color")).get(getArguments().getInt("item")));view.<TextView>findViewById(R.id.tv_show).setText("第 " + (getArguments().getInt("item") + 1) + " 个页面");super.onViewCreated(view, savedInstanceState);}
}

这里有一个静态方法 来接收 传入的数据。
这里 Activity 与 RadioGroup 与ViewPager 2 连用方式 很相似的没什么可说的,不再复述。

c、 google 官方 bug

仔细观察这个案例 ,你会发现在ViewPager 2滑动的时候 TabLayout 的下划线切换了,但是 TabLayout 的字体颜色没有随之改变,但是在点击T abLayout 的 tab 标签的时候,下面的下划线和 ViewPager 2 是联动效果是有的,目前百度里各个大佬是没有解决方案的,所以笔者把这个 bug 提交给了 google 官方就是下面这个样子

现在陡然觉得,学英语真有用。

四、源码

闲话不多说了把源码贴上
源码

ViewPager 2 使用讲解相关推荐

  1. android ViewPager滑动事件讲解

    首先ViewPager在处理滑动事件的时候要用到OnPageChangeListener OnPageChangeListener这个接口需要实现三个方法:(onPageScrollStateChan ...

  2. ViewPager使用讲解

    ViewPager的使用讲解 ViewPager的几个主要逻辑: 一.自动轮播逻辑: 1.使用Handler发送一个延时消息来启动自动轮播 2.在handleMessage方法中,先获取当前页面,然后 ...

  3. ViewPager onPageChangeListener总结

    android ViewPager滑动事件讲解 今天在做项目的时候,由于要处理viewPager页面滑动的事件,所以对其进行了一个小小的研究: 首先ViewPager在处理滑动事件的时候要用到OnPa ...

  4. BAT Android面试专题深入探究:四大组件+ViewPager+组件化架构+Bitmap

    本篇是结合我之前面试别人的经验,以及跟一些在BAT上班的朋友,讨论总结出的一份很深的大公司需要用到的一些高端Android技术.这里也专门整理了一个文档,重点和难点都有详细解析.这些题目有点技术含量, ...

  5. Android Material Design 系列之 BottomNavigationView + ViewPager + Fragment + BadgeView 开发详解

    前言 BottomNavigationView 是 Material Design 提供的一个标准底部导航栏的实现,可以轻松的实现导航栏菜单之间的切换与浏览.底部导航使用户更方便的查看和切换最高层级的 ...

  6. Android之ViewPager讲解

    ViewPager的功能提供界面切换的效果,我们可以定义一组VIEW,在当前界面中进行左右切换它们. 使用ViewPager时我们需要以下准备: 1.准备适配器: <span style=&qu ...

  7. ViewPager,TabLayout,Fragment实现tabs滑动

    工作半年了,准备在新的一年开始写点博客,记录自己的成长,如果能给别人一些参考就更好了. Demo实现: 前段时间公司的项目遇到了使用 ViewPager,TabLayout 和 Fragment实现一 ...

  8. Android中Fragment+ViewPager的配合使用

    原本在上一篇博客中要讲解一个Fragment的综合应用,但是中间又想到了滑屏方式,所以就分类在总结了一下,(http://smallwoniu.blog.51cto.com/3911954/13089 ...

  9. ViewPager 详解(三)---PagerTabStrip与PagerTitleStrip添加标题栏的异同

     相关文章: 1.<ViewPager 详解(一)---基本入门> 2.<ViewPager 详解(二)---详解四大函数> 3.<ViewPager 详解(三)-- ...

  10. 【Android UI设计与开发】第02期:引导界面(二)使用ViewPager实现欢迎引导页面

    转载请注明出处:http://blog.csdn.net/yangyu20121224/article/details/8980917 本系列文章都会以一个程序的实例开发为主线来进行讲解,以求达到一个 ...

最新文章

  1. Halcon与QT的联合编程(1)
  2. k8s 集群 Ingress Nginx传递用户真实IP问题
  3. 看大神如何使用vue导出pdf
  4. Vmware 中Windows和虚拟机共享文件--VMware-tools补丁安装
  5. 点击别的地方隐藏下拉列表
  6. Java的新项目学成在线笔记-day6(五)
  7. Faster RCNN解析
  8. java 匹配mysql按钮_使用Java在mysql查询中设置匹配函数
  9. Java 笔试题---Java与编程模式--7月6日
  10. C#套接字和windowsAPI套接字
  11. C++ tbb unsafe_erase() 并发访问 解决方案
  12. 2015 2020 r4烧录卡 区别_行业新闻2020年中国智能门锁行业发展现状分析
  13. 大学计算机案例教程旧照片修复,「教你一招」使用自动软件修复老照片
  14. [App Bundle]Android动态化技术实例
  15. 实验室信息化管理LIMS 系统常见功能
  16. 服务器知识:关于阿里云服务器域名备案内容
  17. 那些年,被我们误解的程序员
  18. 【视点】从一些实例看大数据部门的权与责
  19. SMM项目登录注册简单实现
  20. CoffeeScript入门

热门文章

  1. 基于大数据的资金流量分析:思路与应用前景设想
  2. MZY项目笔记:session歧路
  3. android studio 圆形头像,Android Studio实现带边框的圆形头像
  4. php 内网/外网ip判断
  5. 【备忘】Aegisub字幕制作简易方法
  6. 方差公式初三_九年级同步数学公式:方差公式(1)
  7. 【回归预测-ELM预测】基于遗传算法优化极限学习机实现风电数据回归预测附matlab代码
  8. java字符串去空格、制表符、换页符
  9. python取出列表的第一列_python取第一列
  10. Go 环境变量、go env