前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发笔记(一百七十二)第二代翻页视图ViewPager2

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

作者头像
aqi00
发布2020-06-24 16:58:55
2.1K0
发布2020-06-24 16:58:55
举报
文章被收录于专栏:老欧说安卓老欧说安卓

正如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节点内部补充以下两行依赖配置:

代码语言:javascript
复制
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    implementation 'androidx.viewpager2:viewpager2:1.0.0'

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

代码语言:javascript
复制
    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/vp2_content"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

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

代码语言:javascript
复制
<!-- 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>

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

代码语言:javascript
复制
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代码,把二代翻页视图的排列方向设为水平方向,并将上述的循环适配器对象设成二代翻页视图的适配器。只要以下寥寥几行代码就搞定了:

代码语言:javascript
复制
    // 从布局文件中获取名叫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代码中补充下面几行:

代码语言:javascript
复制
    // 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代码中补充下面几行:

代码语言:javascript
复制
    // 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的新型适配器代码例子:

代码语言:javascript
复制
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标签,具体内容如下所示:

代码语言:javascript
复制
<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把标签布局跟翻页视图连为一体,关键代码示例如下:

代码语言:javascript
复制
    // 从布局文件中获取名叫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,初始的演示页面如下图所示。

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

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-06-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档