Android ViewPager2 的各种使用方法

前言:

各位同学大家好,有段时间没有给各位更新文章了。在这里给大家拜个晚年,新年快乐,虎年大吉。今天要分享的是viewpager2的使用 废话不多说我们正式开始。

官方使用指南

使用 ViewPager2 创建包含标签的滑动视图

滑动视图允许您通过水平手指手势或滑动在同级屏幕(例如标签页)之间进行导航。此导航模式也称为“水平分页”。本主题介绍了如何创建具有滑动视图(以便在标签页之间切换)的标签页布局,以及如何显示标题条而不是标签页。

官方地址: https://developer.android.google.cn/guide/navigation/navigation-swipe-view-2?hl=zh_cn#java
有兴趣的同学可以自己Android 官网看看
从官方介绍我们可以知道 viewpager2 算是原来的viewpager 的加强版 支持了纵向的滑动 能更好的帮助开发实现类似抖音这类直播的 竖屏视频的滑动效果 。

需要用到的三方库

    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    implementation 'androidx.viewpager2:viewpager2:1.0.0'
    implementation 'com.google.android.material:material:1.0.0'
  • 横向滑动效果

横向滑动.gif

具体实现:

<?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=".HorizontalActivity">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/horizontal_viewpager2"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </androidx.viewpager2.widget.ViewPager2>
   
</androidx.constraintlayout.widget.ConstraintLayout>
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import android.os.Bundle;
/**
 *
 *
 * 创建人: xuqing
 * 创建时间:2022年2月8日11:24:58
 * 类说明: viewpager2 实现横向滑动
 *
 */
public class HorizontalActivity extends AppCompatActivity {
    private ViewPager2 viewPager2;
    private VerticalVpAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_horizontal);
        viewPager2=findViewById(R.id.horizontal_viewpager2);
        adapter=new VerticalVpAdapter(HorizontalActivity.this);
        viewPager2.setAdapter(adapter);
    }
}

布局非常简单就一个viewpager2

适配器

package com.example.myapplication;

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 java.util.ArrayList;
import java.util.List;

public class VerticalVpAdapter extends RecyclerView.Adapter<VerticalVpAdapter.VerticalVpViewHolder> {

    private List<Integer> backgrounds;
    private Context mContext;

    VerticalVpAdapter(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
    @Override
    public VerticalVpViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new VerticalVpViewHolder(LayoutInflater.from(mContext).inflate((R.layout.item_h_v), parent, false));
    }

    @SuppressLint("SetTextI18n")
    @Override
    public void onBindViewHolder(@NonNull VerticalVpViewHolder holder, int position) {
        holder.mTextView.setText("第  " + (position + 1) + " 界面");
        holder.mLinearLayout.setBackgroundResource(backgrounds.get(position));
    }
    @Override
    public int getItemCount() {

        if (backgrounds == null) {
            return 0;
        }
        return backgrounds.size();
    }

    class VerticalVpViewHolder extends RecyclerView.ViewHolder {
        LinearLayout mLinearLayout;
        TextView mTextView;

        VerticalVpViewHolder(@NonNull View itemView) {
            super(itemView);
            mLinearLayout = itemView.findViewById(R.id.ll_h_v);
            mTextView = itemView.findViewById(R.id.tv_hv);
        }
    }
}

和 recylerview的适配器写法很类似 不用我们程序员再去处理viewhodler的复用

  • 竖向滑动效果

竖向滑动.gif

竖向滑动其实跟横向滑动写法差不多 就是在主布局多了一个 android:orientation="vertical" 纵向的属性 这个默认是 横向的 如果你不设置就默认横向滑动

<?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=".VerticalActivity"

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

</androidx.constraintlayout.widget.ConstraintLayout>
  • 横向图片滑动效果


    横向图片滑动.gif

布局

<?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=".HorizontalImageActivity">

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

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.List;


public class HorizontalImageActivity extends AppCompatActivity {
    private int[]image={R.drawable.image1,R.drawable.image2,R.drawable.image3,R.drawable.image4,R.drawable.image5};
    private ImageslideAdapter imageslideAdapter;
    private List<Integer> data=new ArrayList<>();
    private ViewPager2 viewPager2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_horizontal_image);
        for (int i = 0; i <image.length; i++) {
            data.add(image[i]);
        }
        viewPager2=findViewById(R.id.image_viewpager2);
        imageslideAdapter=new ImageslideAdapter(data, HorizontalImageActivity.this);
        viewPager2.setAdapter(imageslideAdapter);
    }

}

适配器

package com.example.myapplication;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;


/***
 *
 *
 * 创建人:xuqing
 * 创建时间:2022年2月8日12:28:21
 * 类说明:图片滑动
 *
 *
 */

public class ImageslideAdapter extends RecyclerView.Adapter<ImageslideAdapter.ImageslideViewHolder> {

    private List<Integer> imageViews;
    private Context context;


    public ImageslideAdapter(List<Integer> imageViews, Context context) {
        this.imageViews = imageViews;
        this.context = context;
    }



    @NonNull
    @Override
    public ImageslideViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new ImageslideAdapter.ImageslideViewHolder(LayoutInflater.from(context).inflate((R.layout.image_item), parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull ImageslideViewHolder holder, int position) {
       holder.imageView.setImageResource(imageViews.get(position));

    }

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

    class ImageslideViewHolder extends RecyclerView.ViewHolder {
        ImageView imageView;
        ImageslideViewHolder(@NonNull View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.item_image);

        }
    }
}

图片滑动其实跟普通布局效果差不多 这边只是item 子布局里面放了一个imgaeview 然后我在实例化的时候传入了图片id的集合 这边可以选择网络图片也可以本地 我方便演示就直接用了本地 其实我们通过接口请求返回的也是可以的

  • 纵向图片滑动同理

横向图片滑动.gif
![横向图片滑动].gif](https://upload-images.jianshu.io/upload_images/6865547-dceb731e18e8b4c9.gif?imageMogr2/auto-orient/strip)

<?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=".VerticaimageActivity">

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

</androidx.constraintlayout.widget.ConstraintLayout>

我们只需要在主布局容器里面加上 android:orientation="vertical" 属性即可

  • ViewPager 2 与 TabLayout 混用

tab.gif
<?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.TabLayout
        android: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.ViewPager2
        android:id="@+id/vp_tb"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
package com.example.myapplication.withTab;

import android.graphics.Color;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import com.example.myapplication.R;
import com.google.android.material.tabs.TabLayout;

public class TabActivity extends AppCompatActivity {

    private ViewPager2 vpTab;
    private TabLayout tabVp;

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

        TabAdapter adapter = new TabAdapter(this);
        vpTab = findViewById(R.id.vp_tb);
        tabVp = findViewById(R.id.tb_vp);
        vpTab.setAdapter(adapter);
        tabVp.setTabTextColors(Color.parseColor("#111111"), Color.parseColor("#0371DD"));

        adapter.addColor(android.R.color.darker_gray);
        adapter.addColor(android.R.color.holo_red_dark);
        adapter.addColor(android.R.color.holo_green_dark);
        adapter.addColor(android.R.color.holo_blue_dark);
        adapter.addColor(android.R.color.holo_purple);
        adapter.addColor(android.R.color.holo_orange_dark);

        tabVp.addTab(tabVp.newTab().setText("第一个界面"));
        tabVp.addTab(tabVp.newTab().setText("第二个界面"));
        tabVp.addTab(tabVp.newTab().setText("第三个界面"));
        tabVp.addTab(tabVp.newTab().setText("第四个界面"));
        tabVp.addTab(tabVp.newTab().setText("第五个界面"));
        tabVp.addTab(tabVp.newTab().setText("第六个界面"));

        tabVp.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                vpTab.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });

        vpTab.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
                tabVp.setScrollPosition(position, 0, false);
            }
        });
    }
}

通过 调用 addOnTabSelectedListener 和 registerOnPageChangeCallback 两个方法来监听 点击和滑动动作

ViewPager 2 与 RadioButton 混用

底部导航滑动.gif
<?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.ViewPager2
        android:id="@+id/vp_rg"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/rg_vp" />

    <RadioGroup
        android: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">

        <RadioButton
            android: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:textSize="16sp" />

        <RadioButton
            android: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:textSize="16sp" />

        <RadioButton
            android: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:textSize="16sp" />
    </RadioGroup>
</RelativeLayout>

activity 逻辑

package com.example.myapplication.withRadioGroup;

import android.os.Bundle;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import com.example.myapplication.R;

public class RgActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener {

    private ViewPager2 vpRg;

    @Override
    protected 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() {
            @Override
            public 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;
                }
            }
        });

    }

    @Override
    public 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 来监听 滑动的时候我们来处理 RadioButton 选中的情况

适配器


package com.example.myapplication.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;

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
    @Override
    public Fragment createFragment(int position) {
        try {
            return (Fragment) fragments.get(position).newInstance();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        return null;
    }

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

这里的适配我们要继承FragmentStateAdapter 才能实现

最后总结:

viewpager2 对比viewpager 功能要强大很多 如果我们开发新的app项目我强烈建议直接使用viewpager2 因为viewpager支持功能 viewpager2 都是支持 我们也更好保证代码统一性 。viewpager2 支持了纵向滑动 让我们可以实现类似抖音等小视频app的部分效果。有兴趣的同学可以下载代码好好研究下或者去看看官方文档 都是可以的 最后祝愿各位网友和同学 2022年心想事成 往事如意 我要继续工作了 ,希望我的文章能帮助到各位解决问题 ,以后我还会贡献更多有用的代码分享给大家。各位同学如果觉得文章还不错 ,麻烦给关注和star,小弟在这里谢过啦!

项目地址:

码云 https://gitee.com/qiuyu123/viewpager2demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,923评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,154评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,775评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,960评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,976评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,972评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,893评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,709评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,159评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,400评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,552评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,265评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,876评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,528评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,701评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,552评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,451评论 2 352

推荐阅读更多精彩内容