正如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标签:
因为ViewPager2仍然需要适配器,所以先编写每项视图的布局文件,下面便是一个XML布局例子,布局上方是图像视图,下方是文本视图。
然后给上面的视图项补充对应的循环适配器代码,传入一个商品列表,再展示每个商品的图片与文字描述。适配器的代码片段示例如下:
public class MobileRecyclerAdapter extends RecyclerView.Adapter {
private Context mContext; // 声明一个上下文对象
private List mGoodsList = new ArrayList(); // 声明一个商品列表
public MobileRecyclerAdapter(Context context, List 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 mGoodsList = new ArrayList(); // 声明一个商品列表
// 碎片页适配器的构造方法,传入碎片管理器与商品信息列表
public MobilePagerAdapter(FragmentActivity fa, List 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标签,具体内容如下所示:
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开发笔记的完整目录