ViewPager2 使用

一、什么是ViewPager?

布局管理器允许左右翻转带数据的页面,你想要显示的视图可以通过实现PagerAdapter来显示。这个类其实是在早期设计和开发的,它的API在后面的更新之中可能会被改变,当它们在新版本之中编译的时候可能还会改变源码。


ViewPager经常用来连接Fragment,它很方便管理每个页面的生命周期,使用ViewPager管理Fragment是标准的适配器实现。最常用的实现一般有FragmentPagerAdapter和FragmentStatePagerAdapter。

ViewPager是android扩展包v4包中的类,这个类可以让我们左右切换当前的view。我们先来聊聊ViewPager的几个相关知识点:

  • 1、ViewPager类直接继承了ViewGroup类,因此它一个容器类,可以添加其他的view类
  • 2、ViewPager类需要一个PagerAdapter适配器类给它提供数据(这点跟ListView一样需要数据适配器Adater)
  • 3、ViewPager经常和Fragment一起使用,并且官方还提供了专门的FragmentPagerAdapterFragmentStatePagerAdapter类供Fragment中的ViewPager使用

二、什么是ViewPager2

原理: viewpager2 内部实现原理是使用recycleview加LinearLayoutManager实现竖直滚动,其实可以理解为对recyclerview的二次封装

private void initialize(Context context, AttributeSet attrs) {
    mAccessibilityProvider = sFeatureEnhancedA11yEnabled
    ? new PageAwareAccessibilityProvider()
    : new BasicAccessibilityProvider();

    // 实例化recycleview对象
    mRecyclerView = new RecyclerViewImpl(context);
    mRecyclerView.setId(ViewCompat.generateViewId());
    mRecyclerView.setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS);

    // 实例化LinearLayoutManager对象
    mLayoutManager = new LinearLayoutManagerImpl(context);
    mRecyclerView.setLayoutManager(mLayoutManager);
    mRecyclerView.setScrollingTouchSlop(RecyclerView.TOUCH_SLOP_PAGING);
    setOrientation(context, attrs);

    mRecyclerView.setLayoutParams(
        new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    mRecyclerView.addOnChildAttachStateChangeListener(enforceChildFillListener());

    // Create ScrollEventAdapter before attaching PagerSnapHelper to RecyclerView, because the
    // attach process calls PagerSnapHelperImpl.findSnapView, which uses the mScrollEventAdapter
    mScrollEventAdapter = new ScrollEventAdapter(this);
    // Create FakeDrag before attaching PagerSnapHelper, same reason as above
    mFakeDragger = new FakeDrag(this, mScrollEventAdapter, mRecyclerView);
    mPagerSnapHelper = new PagerSnapHelperImpl();
    mPagerSnapHelper.attachToRecyclerView(mRecyclerView);
    // Add mScrollEventAdapter after attaching mPagerSnapHelper to mRecyclerView, because we
    // don't want to respond on the events sent out during the attach process
    mRecyclerView.addOnScrollListener(mScrollEventAdapter);

    mPageChangeEventDispatcher = new CompositeOnPageChangeCallback(3);
    mScrollEventAdapter.setOnPageChangeCallback(mPageChangeEventDispatcher);

    // Callback that updates mCurrentItem after swipes. Also triggered in other cases, but in
    // all those cases mCurrentItem will only be overwritten with the same value.
    final OnPageChangeCallback currentItemUpdater = new OnPageChangeCallback() {
        @Override
        public void onPageSelected(int position) {
            if (mCurrentItem != position) {
                mCurrentItem = position;
                mAccessibilityProvider.onSetNewCurrentItem();
            }
        }

        @Override
        public void onPageScrollStateChanged(int newState) {
            if (newState == SCROLL_STATE_IDLE) {
                updateCurrentItem();
            }
        }
    };

    // Prevents focus from remaining on a no-longer visible page
    final OnPageChangeCallback focusClearer = new OnPageChangeCallback() {
        @Override
        public void onPageSelected(int position) {
            clearFocus();
            if (hasFocus()) { // if clear focus did not succeed
                mRecyclerView.requestFocus(View.FOCUS_FORWARD);
            }
        }
    };

    // Add currentItemUpdater before mExternalPageChangeCallbacks, because we need to update
    // internal state first
    mPageChangeEventDispatcher.addOnPageChangeCallback(currentItemUpdater);
    mPageChangeEventDispatcher.addOnPageChangeCallback(focusClearer);
    // Allow a11y to register its listeners after currentItemUpdater (so it has the
    // right data). TODO: replace ordering comments with a test.
    mAccessibilityProvider.onInitialize(mPageChangeEventDispatcher, mRecyclerView);
    mPageChangeEventDispatcher.addOnPageChangeCallback(mExternalPageChangeCallbacks);

    // Add mPageTransformerAdapter after mExternalPageChangeCallbacks, because page transform
    // events must be fired after scroll events
    mPageTransformerAdapter = new PageTransformerAdapter(mLayoutManager);
    mPageChangeEventDispatcher.addOnPageChangeCallback(mPageTransformerAdapter);

    attachViewToParent(mRecyclerView, 0, mRecyclerView.getLayoutParams());
}

ViewPager2的出现是为了替代ViewPager,它有以下几个优势:

  • 支持RTL布局,
  • 支持竖向滚动
  • 支持notifyDataSetChanged

RTL布局是Right To Left布局也就是从右往左的布局,大家知道我们平常写的布局都是从左往右,但是如果你适配阿拉伯语等环境的UI布局,他们的写法是从右往左的,具体这里不做研究。

API的变动:

FragmentStateAdapter替换了原来的 FragmentStatePagerAdapter

RecyclerView.Adapter替换了原来的 PagerAdapter

registerOnPageChangeCallback替换了原来的 addPageChangeListener

FragmentStateAdapter和FragmentStatePagerAdapter作用相同, 可以用viewpager来管理fragment, 区别在于viewpager2的FragmentStateAdapter与recycleview的生命周期绑定

另外viewpager2的Adapter是继承自recyclerview的adapter, 支持除了notifyDataSetChanged()以外的notifyItemChanged(int position)等方式, 使用上更加的便捷

三、ViewPager2 结合 Fragment实际demo

在app模块的build.gradle里要加上这两个依赖

implementation "androidx.viewpager2:viewpager2:1.1.0-beta02"
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'

myfragment.xml

一个显示在屏幕正中央的文字mode1

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FF9800"
    android:orientation="vertical"
    android:gravity="center">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="mode1"
        android:textSize="30sp"/>
</LinearLayout>

myfragment2.xml

一个显示在屏幕正中央的文字mode2

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FF0000"
    android:orientation="vertical"
    android:gravity="center">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="mode2"
        android:textSize="30sp"/>
</LinearLayout>

activity_main.xml

一个TabLayout和一个ViewPager2组件

<?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=".MainActivity">
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/my_tab"
        android:layout_width="match_parent"
        android:layout_height="60dp"/>
    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/my_pager2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

MyAdapter.java

重写MyAdapter、createFragment、getItemCount三个方法

package com.example.viewpager2;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.lifecycle.Lifecycle;
import java.util.List;

public class MyAdapter extends FragmentStateAdapter {

    List<Fragment> fragments;

    public MyAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle, List<Fragment> fragments) {
        super(fragmentManager, lifecycle);
        this.fragments = fragments;
    }

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

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

MyFragment.java

实现第一个fragment页面

package com.example.viewpager2;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class MyFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.myfragment, null);
    }
}

MySecondFragment.java

实现第二个fragment页面

package com.example.viewpager2;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class MySecondFragment extends Fragment {

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.myfragment2, null);
    }

}

MainActivity.java

进来的activity

package com.example.viewpager2;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.widget.ViewPager2;

import android.os.Bundle;

import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private TabLayout myTab;
    private ViewPager2 myPager2;

    List<String> titles=new ArrayList<>();
    List<Fragment> fragments=new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myTab = findViewById(R.id.my_tab);
        myPager2 = findViewById(R.id.my_pager2);

        //添加标题
        titles.add("1");
        titles.add("2");

        //添加Fragment进去
        fragments.add(new MyFragment());
        fragments.add(new MySecondFragment());

        //实例化适配器
        MyAdapter myAdapter=new MyAdapter(getSupportFragmentManager(),getLifecycle(),fragments);
        //设置适配器
        myPager2.setAdapter(myAdapter);
        //TabLayout和Viewpager2进行关联
        new TabLayoutMediator(myTab, myPager2, new TabLayoutMediator.TabConfigurationStrategy() {
            public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
                tab.setText(titles.get(position));
            }
        }).attach();

    }
}

ViewPager + Fragment 实现tab页切换不同页面内容的效果

参考:【精选】Android:ViewPager \ViewPager2 简单介绍 & 使用方法解析_viewpager2与viewpager-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/121806.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

服务器数据恢复—误还原虚拟机快照后如何恢复之前的数据?

服务器数据恢复环境&#xff1a; vmfs文件系统&#xff0c;存放的是SqlServer数据库及其他办公文件。 服务器故障&#xff1a; 工作人员误操作还原快照&#xff0c;导致了SqlServer数据库数据丢失。 服务器数据恢复过程&#xff1a; 1、拿到故障服务器的所有磁盘后&#xff0c…

学习c++的第十天

目录 类 & 对象 类定义 对象的建立和使用 构造函数(Constructor) 析构函数(Destructor) 拷贝构造函数 扩展知识 this指针 友元函数的使用方法 友元类的使用方法 常数据的使用及初始化 类 & 对象 什么是类&#xff1f;什么是对象&#xff1f;对于面向对象的…

阶段七-Day02-Spring02

一、Spring的注解支持 1. 为什么使用Spring注解 在昨天的练习中有这样的一段代码&#xff0c;为了给UserServiceImpl注入UserMapper对象。 2. Spring支持的注解&#xff08;IoC/DI相关&#xff09; 下面Repository、Service、Controller、Configuration都是Component注解的…

SpringBoot整合Swagger3,赶紧整起来!

文章目录 一、Swagger是什么&#xff1f;二、使用步骤1.引入swagger3依赖2.添加swagger.conf配置类3.添加application.yml配置4.查看是否整合成功5.常用注解6.swagger美化 总结 一、Swagger是什么&#xff1f; Swagger 是一个规范和完整的框架&#xff0c;用于生成、描述、调用…

嵌入式养成计划-51----ARM--ARM汇编指令--内存读写指令--程序状态寄存器传输指令--软中断指令--混合编程

一百二十七、内存读写指令 通过内存读写指令可以实现向内存中写入指定数据或者读取指定内存地址的数据 127.1 单寄存器内存读写指令 将一个寄存器中的数值写入到内存&#xff0c;或者从内存中读取数据放在某一个指定寄存器中 127.1.1 指令码和功能 1. 向内存中写&#xff…

浙大软院2024届推免录取名单及分析

名单 分析 浙大软院共录取电子信息专业推免生219人&#xff0c;机械专业推免生20人 小Tips&#xff1a;浙大软院夏令营考核时间比较长&#xff0c;并且不发offer&#xff0c;但是如果夏令营能拿到优营能够直入预推免哦&#xff0c;以浙大为梦校并且背景不是特别好的同学可以多…

JS逆向爬虫---请求参数加密③【比特币交易爬虫】

查询参数确定 t无加密 请求头参数加密 X-Apikey参数加密确定 X-Apikey逆向 const API_KEY "a2c903cc-b31e-4547-9299-b6d07b7631ab" function encryptApiKey(){ var t API_KEY, e t.split(""), n e.splice(0, 8);return t e.concat(n).join("&…

ChatGPT:something went wrong

今天下午不知什么原因&#xff0c;ChatGPT无法使用。我原来在使用ChatGPT for chrome&#xff0c;返回了一个答案&#xff0c;后来在网页端无法使用&#xff0c;以为是这个chrome插件泄露API KEY导致的。注销账号&#xff0c;删除API KEY后&#xff0c;wrong问题仍然存在。 我…

kafka笔记要点和集群安装、消息分组、消费者分组以及与storm的整合机制

kafka笔记 1/kafka是一个分布式的消息缓存系统 2/kafka集群中的服务器都叫做broker 3/kafka有两类客户端&#xff0c;一类叫producer&#xff08;消息生产者&#xff09;&#xff0c;一类叫做consumer&#xff08;消息消费者&#xff09;&#xff0c;客户端和broker服务器之间…

维修服务预约小程序的内容是什么

维修服务往往有较高市场需求度&#xff0c;常见的就是电器维修和外部建工维修等&#xff0c;相关从业商家众多且竞争激烈&#xff0c;因为大多为区域性发展&#xff0c;因此更需要拓展品牌、打通服务宣传路径&#xff0c;获客增长生意。 然而在实际发展中&#xff0c;维修服务…

v-calendar 日历组件使用自定义提示内容

目录 0.介绍 1.安装v-calendar 2.页面使用 3.使用插槽实现待办数量的标记 0.介绍 最近项目中用到了日历插件&#xff0c;需要统计每天的任务数量&#xff0c;类似elementui的badge组件&#xff0c;待办任务数量 大概最后的效果如下图所示&#xff0c;右上角把代办任务数量…

爱上C语言:操作符详解(上)

&#x1f680; 作者&#xff1a;阿辉不一般 &#x1f680; 你说呢&#xff1a;生活本来沉闷&#xff0c;但跑起来就有风 &#x1f680; 专栏&#xff1a;爱上C语言 &#x1f680;作图工具&#xff1a;draw.io(免费开源的作图网站) 如果觉得文章对你有帮助的话&#xff0c;还请…

docker 构建并运行 python项目

此处不重述docker安装及基本命令&#xff0c;可参考另一篇文章centos7 安装 docker_centos7 docker network rm-CSDN博客文章浏览阅读111次。1、 1.1 docker 官网 Empowering App Development for Developers | DockerLearn how Docker helps developers bring their ideas to …

使用Drupal管理小型项目?试试Docker快速部署Drupal结合内网穿透实现远程访问

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525;个人专栏:《Linux深造日志》《C干货基地》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 前言1. Docker安装Drupal2. 本地局域网访问3 . Linux 安装cpolar4. 配置Drupal公网访问地址5. 公网远程访问Drupal…

简析电能管理系统在某煤矿的应用

叶根胜 安科瑞电气股份有限公司 上海嘉定 201801 摘要&#xff1a;针对传统的煤矿电能管理主要是由专人人工抄表&#xff0c;存在抄收数据繁琐&#xff0c;统计困难&#xff0c;煤矿用电分析等方面数据缺乏&#xff0c;电量峰谷比不合理等问题。某煤矿应用电能管理系统&#…

【紫光同创国产FPGA教程】——【PGL22G第九章】HDMI环路实验例程

本原创教程由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处 适用于板卡型号&#xff1a; 紫光同创PGL22G开发平台&#xff08;盘古22K&#xff09; 一&#xff1a;盘古22K开发板&#xff08;紫光同创PGL22G开…

OpenSign 开源 PDF 电子签名解决方案

OpenSign 是一个开源文档电子签名解决方案&#xff0c;旨在为 DocuSign、PandaDoc、SignNow、Adobe Sign、Smartwaiver、SignRequest、HelloSign 和 Zoho Sign 等商业平台提供安全、可靠且免费的替代方案。 特性&#xff1a; 安全签名&#xff1a;利用最先进的加密算法来确保…

Oracle RAC是啥?

Oracle RAC&#xff0c;全称是Oracle Real Application Cluster&#xff0c;翻译过来为Oracle真正的应用集群&#xff0c;它是Oracle提供的一个并行集群系统&#xff0c;由 Oracle Clusterware&#xff08;集群就绪软件&#xff09; 和 Real Application Cluster&#xff08;RA…

1.docker linux离线环境安装 20.1.0.12

目录 概述下载解压docker 卸载docker 安装检查安装环境常用命令结束 概述 docker离线环境安装 20.1.0.12 , centos 7.x 下载 安装包下载 解压 [roothadoop01 soft]# unzip docker_20_1_0_12.zip [roothadoop01 soft]# cd docker_20_1_0_12 [roothadoop01 docker_20_1_0_1…

Linux 设置静态IP(Ubuntu 20.04/18.04)

以Ubuntu20.04示例 第一步&#xff1a;查看当前网络信息 ifconfig 本机网卡名为&#xff1a;ens32&#xff0c;IP地址为&#xff1a;192.168.15.133&#xff0c;子网掩码为&#xff1a;255.255.255.0 第二步&#xff1a;查看当前网关信息 route -n 网关地址为&#xff1a;1…