ViewPager2学习总结

Posted AC_Jobim

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ViewPager2学习总结相关的知识,希望对你有一定的参考价值。

一、ViewPage2的介绍

API changes:

FragmentStateAdapter 替代 FragmentStatePagerAdapter
RecyclerView.Adapter 替代 PagerAdapter
registerOnPageChangeCallback 替代 addPageChangeListener

官方文档
https://developer.android.google.cn/jetpack/androidx/releases/viewpager2#1.0.0-alpha01

官方Demo
https://github.com/googlesamples/android-viewpager2

常用方法API:

//刷新Viewpager 同样支持recyclerView的局部刷新
notifyDataSetChanged()
 
setUserInputEnabled(false);//禁止手动滑动
 
setCurrentItem(0, false);//跳转到指定页面,false不带滚动动画
 
setCurrentItem(0);//跳转到指定页面,带滚动动画
 
addItemDecoration()//设置分割线 同RecyclerView
 
setOffscreenPageLimit();//设置预加载数量
 
setOrientation();//设置方向
 
fakeDragBy(offsetPx)//代码模拟用户滑动页面。支持通过编程方式滚动。
 
setPageTransformer()//设置滚动动画,参数可传 CompositePageTransformer,PageTransformer

中间件(TabLayoutMediator):

TabLayoutMediator是连接TabLayout与ViewPager2的中介。当选项卡被选中时,中介将同步ViewPager2的位置与所选的选项卡,以及当用户拖动ViewPager2时同步TabLayout的滚动位置。其具体特性与使用可以参考链接内容。

添加依赖:

implementation 'androidx.viewpager2:viewpager2:1.0.0'

二、ViewPager2与RecycleView的结合使用

效果展示:
在这里插入图片描述

项目结构如下:
在这里插入图片描述
activity_main.xml代码

<?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"
    tools:context=".MainActivity">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewpager2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

MainActivity的代码

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewPager2 viewPager2 = findViewById(R.id.viewpager2);
        ViewPagerAdapter adapter = new ViewPagerAdapter(this);
        viewPager2.setAdapter(adapter);

    }
}

列表Item的布局item_pager.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:id="@+id/rl_container">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tv_title"
        android:textSize="40sp"
        android:text="你好"/>

</RelativeLayout>

ViewPagerAdapter的代码如下,使用跟RecycleView的adapter完全一样

package com.zb.viewpager2;

import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

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


public class ViewPagerAdapter extends RecyclerView.Adapter<ViewPagerAdapter.MyHolder> {

    Context mContext;
    private List<String> titles = new ArrayList<>();
    private List<String> colors = new ArrayList<>();

    public ViewPagerAdapter(Context context){
        mContext = context;
        titles.add("one");
        titles.add("two");
        titles.add("three");
        colors.add("#FF44FF");
        colors.add("#EEFFEE");
        colors.add("#EEE000");
    }

    @NonNull
    @Override
    public MyHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_pager,parent,false);
        return new MyHolder(view);
    }

    //进行数据的绑定
    @Override
    public void onBindViewHolder(@NonNull MyHolder holder, int position) {
        holder.tv_title.setText(titles.get(position));
        holder.rl_container.setBackgroundColor(Color.parseColor(colors.get(position)));
    }

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

    class MyHolder extends RecyclerView.ViewHolder{
        TextView tv_title;
        RelativeLayout rl_container;
        public MyHolder(@NonNull View itemView) {
            super(itemView);
            tv_title = itemView.findViewById(R.id.tv_title);
            rl_container = itemView.findViewById(R.id.rl_container);
        }
    }

}

2.1 实现竖直滑动

方法一:布局

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

布局内的 android:orientation=“vertical” 控制横向和纵向滑动

方法二:逻辑

ViewPager2 viewPager2 = findViewById(R.id.viewpager2);
ViewPagerAdapter adapter = new ViewPagerAdapter(this);
viewPager2.setAdapter(adapter);
viewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);//设置为竖直滑动

Activity 内的viewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);可以实现 xml 内的android:orientation="vertical"相同效果。
默认是水平方向ORIENTATION_HORIZONTAL,垂直是ORIENTATION_VERTICAL

三、TabLayout与ViewPager2连用

效果展示:
在这里插入图片描述

项目结构:
在这里插入图片描述

导入TabLayout的依赖

implementation 'com.google.android.material:material:1.3.0'

BlankFragment.java:

public class BlankFragment extends Fragment {

    private static final String ARG_PARAM1 = "param1";

    private String mTextString;
    private View rootView;

    public BlankFragment() {
        // Required empty public constructor
    }

    public static BlankFragment newInstance(String param1) {
        BlankFragment fragment = new BlankFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            //获取bundle中传递的值
            mTextString = getArguments().getString(ARG_PARAM1);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if(rootView == null){
            rootView = inflater.inflate(R.layout.fragment_blank, container, false);
        }
        initView();
        return rootView;
    }

    private void initView() {
        TextView textView = rootView.findViewById(R.id.text_title);
        textView.setText(mTextString);
    }

}

activity_main.xml如下:

<?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">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewpager2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </com.google.android.material.tabs.TabLayout>

</LinearLayout>

设置继承自 FragmentStateAdapter 的类:

public class ViewPagerStateAdapter extends FragmentStateAdapter {

    List<String> strs = new ArrayList<>();

    public ViewPagerStateAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
        super(fragmentManager, lifecycle);
        strs.add("oneFragment");
        strs.add("twoFragment");
        strs.add("threeFragment");
    }


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

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

MainActivity的代码:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TabLayout tabLayout = findViewById(R.id.tab_layout);
        ViewPager2 viewPager2 = findViewById(R.id.viewpager2);

        tabLayout.addTab(tabLayout.newTab().setText("tab1"));
        tabLayout.addTab(tabLayout.newTab().setText("tab2"));
        tabLayout.addTab(tabLayout.newTab().setText("tab3"));

        ViewPagerStateAdapter adapter = new ViewPagerStateAdapter(getSupportFragmentManager(),getLifecycle());
        viewPager2.setAdapter(adapter);

        //添加页签选中监听
        tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                //Viewpager
                viewPager2.setCurrentItem(tab.getPosition());
            }
            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
            }
            @Override
            public void onTabReselected(TabLayout.Tab tab) {
            }
        });

        //注册页面变化的回调接口
        viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
                tabLayout.setScrollPosition(position,0,false);
            }
        });
    }
}

简单方法:用TabLayoutMediator将TabLayout和ViewPager2结合

//用TabLayoutMediator将TabLayout和ViewPager2结合
new TabLayoutMediator(tabLayout, viewPager2, true,new TabLayoutMediator.TabConfigurationStrategy() {
    @Override
    public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
        //这里需要根据position修改tab的样式和文字等
        tab.setText("fragment"+position);
    }
}).attach();

//方式二:
//用TabLayoutMediator将TabLayout和ViewPager2结合
//new TabLayoutMediator(tabLayout, viewPager2, (tab, position) -> tab.setText(strs.get(position))).attach();

以上是关于ViewPager2学习总结的主要内容,如果未能解决你的问题,请参考以下文章

ViewPager2 无法动态添加删除片段

ViewPager2:以编程方式选择特定片段

带有 Viewpager2 的关键 FragmentStateAdapter 的片段不再存在

ViewPager2 中的片段在返回父片段时被重新创建

带有片段和 Jetpack 导航的 Viewpager2:恢复片段而不是重新创建它们

底部导航片段中的 Viewpager2