ViewPager2 使用

news2024/11/26 11:56:26

一、什么是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博客

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

为什么有的孩子玩着玩着就成了学霸?

毫不夸张地说&#xff0c;几乎所有的父母都想养出聪明宝宝&#xff0c;孩子上学之后能成为学霸就更省心了。 可“聪明”毕竟不能量化&#xff0c;不是说让孩子上几天课就能提升的。很多家长都在促进孩子大脑发育上使足了劲&#xff0c;可到头来却发现是在做“无用功”。 事实…

SUSE 12双网卡绑定

原创作者&#xff1a;运维工程师 谢晋 SUSE 12双网卡绑定 客户环境及需求网卡绑定 客户环境及需求 客户一台物理机安装了SUSE 12的操作系统&#xff0c;需要将ETH5和ETH7双网卡聚合为一块虚拟网卡&#xff0c;以保证一块网卡故障不会影响系统正常运行。 网卡绑定 输入命令c…

C#查看启用或关闭的Windows功能

通过命令查看启用或关闭的Windows功能&#xff0c;以管理员身份打开powershell&#xff0c;输入命令get-windowsoptionalfeature -online 得出结果如下&#xff1a; 如果使用C#查看&#xff0c;需要先安装System.Management 代码如下&#xff1a; private void isInstall() …

Unity | Shader(着色器)和material(材质)的关系

一、前言 在上一篇文章中 【精选】Unity | Shader基础知识&#xff08;什么是shader&#xff09;_unity shader_菌菌巧乐兹的博客-CSDN博客 我们讲了什么是shader&#xff0c;今天我们讲一下shder和material的关系 二、在unity中shader的本质 unity中&#xff0c;shader就…

【紫光同创国产FPGA教程】——PDS安装教程

本原创教程由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处 一&#xff1a;软件简介 PangoDesign Suite是紫光同创基于多年FPGA开发软件技术攻关与工程实践经验而研发的一款拥有国产自主知识产权的大规模FPGA开…

软件测评中心▏软件功能测试和非功能测试的区别和联系简析

在软件开发的过程中&#xff0c;功能测试和非功能测试是两个重要的环节。功能测试是指对软件的各项功能进行验证和确认&#xff0c;关注软件是否按照需求规格说明书进行了实现&#xff0c;是否满足了用户的功能需求。而非功能测试是指对软件的性能、可靠性、安全性等方面进行测…

Zabbix之部署代理服务器

一、部署代理服务器 分布式监控的作用 分担server的几种式压力解决多机房之间的网络延时问题 1、搭建proxy主机 1.1 关闭防火墙&#xff0c;修改主机名 systemctl disbale --now firewalld setenforce 0 hostnamectl set-hostname zbx-proxy su1.2 设置zabbix下载源 rpm …

Unity中Shader光照探针的支持

文章目录 前言一、光照探针用在哪怎么用1、光照探针的应用场景2、我们按照以上条件&#xff0c;在Unity中搭建一个相同的环境3、创建光照探针 二、在我们自己的Shader中&#xff0c;实现支持光照探针1、使用常用的 cginc2、在 v2f 中&#xff0c;准备如下变量3、在顶点着色器中…

2023年【安全员-B证】新版试题及安全员-B证免费试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 安全员-B证新版试题参考答案及安全员-B证考试试题解析是安全生产模拟考试一点通题库老师及安全员-B证操作证已考过的学员汇总&#xff0c;相对有效帮助安全员-B证免费试题学员顺利通过考试。 1、【多选题】下列哪些属…

云表:“智、数”结合,低代码赋能制造业,入局者赢

在数智时代&#xff0c;智能制造正崭露头角&#xff0c;它借助先进的信息技术和数据分析工具&#xff0c;将制造业与人工智能紧密结合&#xff0c;推动生产过程的智能化和自动化。通过大数据、云计算、物联网等前沿技术&#xff0c;智能制造实现了生产线的高效、灵活、可定制的…

文件加密软件怎么用(附2种解密破解工具)

有时候出差或者有些商务场合&#xff0c;需要对一些敏感文件做一下简单的加密&#xff0c;这样在分享内容的时候&#xff0c;可以起到初步的保护作用。 当然了&#xff0c;如果文件非常重要&#xff0c;涉及到一些商业机密&#xff0c;这个时候你需要使用专业的加密工具&#x…

陳烨(本烨)老师受聘為香港國學發展研究院客座教授

香港國學發展研究院有幸宣布&#xff0c;中華傳統文化學者陳烨女士已正式受聘為學院的客座教授。陳烨女士是一位備受尊敬的學者&#xff0c;在中華傳統道學文化領域擁有廣泛的知識和卓越的學術成就。   陳烨女士是中華傳統道學文化領域的知名專家。她不僅在教學方面積累了豐富…

挑战100天 AI In LeetCode Day07(热题+面试经典150题)

挑战100天 AI In LeetCode Day07&#xff08;热题面试经典150题&#xff09; 一、LeetCode介绍二、LeetCode 热题 HOT 100-92.1 题目2.2 题解 三、面试经典 150 题-93.1 题目3.2 题解 一、LeetCode介绍 LeetCode是一个在线编程网站&#xff0c;提供各种算法和数据结构的题目&am…

2023禁用谷歌浏览器自动更新最好的解决方式

&#x1f9c1;介绍 对于一些用户来说&#xff0c;Chrome 浏览器的自动更新功能可能会带来一些不便或者不必要的麻烦。 本文将介绍如何使用批处理脚本来停止和禁用 Chrome 的自动更新功能&#xff0c;确保不再进行后台网络操作。文章将详细说明代码的编写和执行步骤。 &#…

FastReport 2023.1.3 基于源码原版本升级 Delphi 12 c++ builder 12

复制 RAD Studio 10.4 为RAD Studio 12 dpk 文本打开 28 改成 29 Build -> install就可以了

福州等保测评机构有几家?正规吗?在哪里?

最近看到不少福州小伙伴在问&#xff0c;福州等保测评机构有几家&#xff1f;正规吗&#xff1f;在哪里&#xff1f;这里小编就给大家来详细解答一下&#xff0c;仅供参考哦&#xff01; 福州等保测评机构有几家&#xff1f;正规吗&#xff1f;在哪里&#xff1f; 【回答】&…

windows系统自动更新中断电导致系统无法开启

windows系统自动更新中断电导致系统无法开启 现象原因解决进入bios拆机更新系统重新安装内存条 现象 前一天晚上电脑出现合上之后风扇继续转的现象&#xff0c;拔掉电源后&#xff0c;第二天开不了机。现象为按压电源键&#xff0c;电源键和充电指示灯亮一次后熄灭&#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 …

SSM 线上知识竞赛系统-计算机毕设 附源码 27170

SSM线上知识竞赛系统 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运用中&#…

从哪些方面做好电商系统的网站建设?

电子商务的迅猛发展&#xff0c;建设一款成功的电商系统网站成为企业取得竞争优势的重要一环。下面将从用户体验、网站设计、安全性和性能优化等方面&#xff0c;介绍如何打造一款优秀的电商系统网站。 一、用户体验 一款成功的电商系统网站必须注重用户体验&#xff0c;确保用…