Android开发笔记(一百七十二)第二代翻页视图ViewPager2

正如RecyclerView横空出世取代ListView和GridView那样,Android也推出了二代翻页视图ViewPager2,打算替换原来的翻页视图ViewPager。与ViewPager相比,ViewPager2支持更丰富的界面特效,包括但不限于下列几点:
1、不但支持水平方向翻页,还支持垂直方向翻页;
2、支持RecyclerView.Adapter,允许调用适配器对象的notifyItem***方法,从而动态刷新某项视图;
3、除了当前页,也支持展示左右两页的部分区域;
4、支持在翻页过程中展示自定义的切换动画;
虽然ViewPager2增加了这么棒的功能,但它用起来非常简单,掌握下面几个方法就够了:
setAdapter:设置二代翻页视图的页面适配器。
setOrientation:设置二代翻页视图的翻页方向。其中ViewPager2.ORIENTATION_HORIZONTAL表示水平方向,ViewPager2.ORIENTATION_VERTICAL表示垂直方向。
setPageTransformer:设置二代翻页视图的页面转换器,以便展示切换动画。
接下来利用循环适配器搭配二代翻页视图,演示看看ViewPager2的界面效果。注意RecyclerView与ViewPager2拥有各自的AndroidX库,故需修改模块的build.gradle,在dependencies节点内部补充以下两行依赖配置:

    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    implementation 'androidx.viewpager2:viewpager2:1.0.0'

接着新建一个活动页面,往该页面的XML文件添加如下所示的ViewPager2标签:

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

因为ViewPager2仍然需要适配器,所以先编写每项视图的布局文件,下面便是一个XML布局例子,布局上方是图像视图,下方是文本视图。

<!-- ViewPager2要求每页的宽高都必须是match_parent -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <ImageView
        android:id="@+id/iv_pic"
        android:layout_width="match_parent"
        android:layout_height="360dp"
        android:scaleType="fitCenter" />
    <TextView
        android:id="@+id/tv_desc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

然后给上面的视图项补充对应的循环适配器代码,传入一个商品列表,再展示每个商品的图片与文字描述。适配器的代码片段示例如下:

public class MobileRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private Context mContext; // 声明一个上下文对象
    private List<GoodsInfo> mGoodsList = new ArrayList<GoodsInfo>(); // 声明一个商品列表
    public MobileRecyclerAdapter(Context context, List<GoodsInfo> goodsList) {
        mContext = context;
        mGoodsList = goodsList;
    }

    // 创建列表项的视图持有者
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup vg, int viewType) {
        // 根据布局文件item_mobile.xml生成视图对象
        View v = LayoutInflater.from(mContext).inflate(R.layout.item_mobile, vg, false);
        return new ItemHolder(v);
    }

    // 绑定列表项的视图持有者
    public void onBindViewHolder(RecyclerView.ViewHolder vh, final int position) {
        ItemHolder holder = (ItemHolder) vh;
        holder.iv_pic.setImageResource(mGoodsList.get(position).pic);
        holder.tv_desc.setText(mGoodsList.get(position).desc);
    }

    // 定义列表项的视图持有者
    public class ItemHolder extends RecyclerView.ViewHolder {
        public ImageView iv_pic; // 声明列表项图标的图像视图
        public TextView tv_desc; // 声明列表项描述的文本视图
        public ItemHolder(View v) {
            super(v);
            iv_pic = v.findViewById(R.id.iv_pic);
            tv_desc = v.findViewById(R.id.tv_desc);
        }
    }
}

回到测试页面的Java代码,把二代翻页视图的排列方向设为水平方向,并将上述的循环适配器对象设成二代翻页视图的适配器。只要以下寥寥几行代码就搞定了:

    // 从布局文件中获取名叫vp2_content的二代翻页视图
    ViewPager2 vp2_content = findViewById(R.id.vp2_content);
    // 设置二代翻页视图的排列方向为水平方向
    vp2_content.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
    // 构建一个商品信息列表的循环适配器
    MobileRecyclerAdapter adapter = new MobileRecyclerAdapter(this, GoodsInfo.getDefaultList());
    vp2_content.setAdapter(adapter); // 设置二代翻页视图的适配器

运行测试App,水平方向的翻页过程如下图所示。


如果把翻页方向改为垂直方向,那么翻页之时的界面如下图所示。


以上的效果图看起来仅仅多了垂直翻页,稍等片刻给它加上其它特效。先在测试页面的Java代码中补充下面几行:

    // ViewPager2支持展示左右两页的部分区域
    RecyclerView cv_content = (RecyclerView) vp2_content.getChildAt(0);
    cv_content.setPadding(Utils.dip2px(this, 60), 0, Utils.dip2px(this, 60), 0);
    cv_content.setClipToPadding(false); // false表示不裁剪下级视图

重新运行测试App,此时页面效果如下图所示,可见除了显示当前商品之外,左右两页也呈现了边缘区域。


撤销刚加的边缘特效代码,再给测试页面的Java代码中补充下面几行:

    // ViewPager2支持在翻页时展示切换动画
    // 创建页面转换器,用于计算切换动画的各项参数
    ViewPager2.PageTransformer animator = new ViewPager2.PageTransformer() {
        @Override
        public void transformPage(@NonNull View page, float position) {
            page.setRotation(position * 360); // 设置页面的旋转角度
        }
    };
    vp2_content.setPageTransformer(animator); // 设置二代翻页视图的页面转换器

重新运行测试App,此时翻页过程如下面两图所示,其中第一张图为开始翻页不久的界面效果,第二张图为翻页即将结束的界面效果,从中可见翻页时展示了旋转动画。

ViewPager2不仅支持循环适配器,同样支持翻页适配器,还是新的哦。原先ViewPager采用的翻页适配器叫做FragmentStatePagerAdapter,而ViewPager2采用了FragmentStateAdapter,两个适配器的名称差了个“Pager”。一看名称不同,用法肯定有差别,尽管它俩都支持碎片Fragment,但具体的方法就不一样了。
比如下面是采用FragmentStateAdapter的新型适配器代码例子:

public class MobilePagerAdapter extends FragmentStateAdapter {
    private List<GoodsInfo> mGoodsList = new ArrayList<GoodsInfo>(); // 声明一个商品列表

    // 碎片页适配器的构造方法,传入碎片管理器与商品信息列表
    public MobilePagerAdapter(FragmentActivity fa, List<GoodsInfo> goodsList) {
        super(fa);
        mGoodsList = goodsList;
    }

    // 创建指定位置的碎片Fragment
    @NonNull
    @Override
    public Fragment createFragment(int position) {
        return MobileFragment.newInstance(position,
                mGoodsList.get(position).pic, mGoodsList.get(position).desc);
    }

    // 获取碎片Fragment的个数
    @Override
    public int getItemCount() {
        return mGoodsList.size();
    }
}


运行测试App观察到的界面效果跟循环适配器差不多,因为展示商品信息的场景比较简单,所以循环适配器和翻页适配器看不出区别。就实际开发而言,简单的业务场景适合采用循环适配器,复杂的业务场景适合采用翻页适配器。
ViewPager有个标签栏搭档PagerTabStrip,然而ViewPager2抛弃了PagerTabStrip,直接跟TabLayout搭配了。如果要让ViewPager联动TabLayout,得先给ViewPager注册页面变更监听器,一旦监听到翻页事件就切换对应的标签;再给TabLayout注册标签选中监听器,一旦监听到标签事件就翻到对应的页面。现在有了ViewPager2,搭配TabLayout便轻松多了,只要一行代码即可绑定ViewPager2与TabLayout。下面是将二者联结起来的操作步骤。
1、创建测试页面,并往页面的XML文件先后加入TabLayout标签和ViewPager2标签,具体内容如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <!-- 标签布局TabLayout节点需要使用完整路径 -->
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <!-- 二代翻页视图ViewPager2节点也需要使用完整路径 -->
    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/vp2_content"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />
</LinearLayout>

2、打开该页面的Java代码,分别获取TabLayout和ViewPager2的视图对象,再利用TabLayoutMediator把标签布局跟翻页视图连为一体,关键代码示例如下:

    // 从布局文件中获取名叫tab_title的标签布局
    TabLayout tab_title = findViewById(R.id.tab_title);
    // 从布局文件中获取名叫vp2_content的二代翻页视图
    ViewPager2 vp2_content = findViewById(R.id.vp2_content);
    // 构建一个商品信息的翻页适配器
    MobilePagerAdapter adapter = new MobilePagerAdapter(this, mGoodsList);
    vp2_content.setAdapter(adapter); // 设置二代翻页视图的适配器
    // 把标签布局跟翻页视图通过指定策略连为一体,二者在页面切换时一起联动
    new TabLayoutMediator(tab_title, vp2_content, new TabLayoutMediator.TabConfigurationStrategy() {
        @Override
        public void onConfigureTab(TabLayout.Tab tab, int position) {
            tab.setText(mGoodsList.get(position).name); // 设置每页的标签文字
        }
    }).attach();

重新运行测试App,初始的演示页面如下图所示。


接着点击上方标签栏的第二个标签,此时页面下方翻到了第二页商品,如下图所示。


然后手指在商品处向左滑动,此时翻到了第三页商品,同时标签栏也切到了第三个标签,如下图所示。由此验证了标签布局与翻页视图的确是绑定到一块了。

 


点此查看Android开发笔记的完整目录

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页