本篇 Blog 记录 ViewPager 和 ViewPager2
嵌套 Fragment 的效果图
ViewPager 的使用
关于 ViewPager 的使用已经很常见了,这里在复习一下吧。配合 TabLayout
-
布局文件
在 ViewPager 的布局中允许存在子 view,我们可以把 TabLayout 作为 ViewPager 的子 View 写在 ViewPager 内部,也可以并列。
<androidx.viewpager.widget.ViewPager
android:id="@+id/vp_merchant_main"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintVertical_weight="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/banner_merchant_main"
app:layout_constraintBottom_toBottomOf="parent">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout_merchant_main"
android:layout_width="match_parent"
android:layout_height="50dp"
app:tabGravity="center"
app:tabIndicatorColor="@color/tabLayoutIndicatorStartColor"
app:tabSelectedTextColor="@color/textColor"
app:tabTextAppearance="@android:style/TextAppearance.Holo"
app:tabTextColor="@color/defaultTextColor" />
</androidx.viewpager.widget.ViewPager>
-
Java 代码
代码中我们只需要把 Fragment 和 Titles 传入 Adapter,然后再设置到 ViewPager 上就可以了。
我们也可以调用 Tablayout 的 setupWithViewPager() 方法使 TabLayout 和 ViewPager 进行绑定
// ViewPager处理
ArrayList<Fragment> fragmentList = new ArrayList<>();
fragmentList.add(new AllProductFragment(this));
fragmentList.add(new EvaluationFragment(this));
String[] fragmentTitles = {"商品", "评价"};
ViewPagerScrollAdapter scrollAdapter = new ViewPagerScrollAdapter(getSupportFragmentManager());
scrollAdapter.setFragmentTitles(fragmentTitles);
scrollAdapter.setMenuFragmentList(fragmentList);
merchantMainBinding.vpMerchantMain.setAdapter(scrollAdapter);
-
Adapter
注意:ViewPager 的 Adapter 需要继承 FragmentStatePagerAdapter
public class ViewPagerScrollAdapter extends FragmentStatePagerAdapter {
private ArrayList<Fragment> menuFragmentList;
private String [] fragmentTitles;
public ViewPagerScrollAdapter(@NonNull FragmentManager fm) {
super(fm);
}
public ViewPagerScrollAdapter(@NonNull FragmentManager fm, int behavior) {
super(fm, behavior);
}
public void setFragmentTitles(String[] fragmentTitles) {
this.fragmentTitles = fragmentTitles;
}
public void setMenuFragmentList(ArrayList<Fragment> menuFragmentList) {
this.menuFragmentList = menuFragmentList;
}
@NonNull
@Override
public Fragment getItem(int position) {
return menuFragmentList.get(position);
}
@Override
public int getCount() {
return menuFragmentList.size();
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return fragmentTitles[position];
}
}
到这儿关于 ViewPager 的基本使用就完成了。下面是 ViewPager2 的使用
ViewPager2 的使用
关于 ViewPager2 嵌套 Fragment 的使用很简单。
-
布局文件
在布局中 ViewPager2 的使用是不允许有自 View 的,我们这里仍然配合 TabLayout 使用。
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout_group"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="@id/vp_group_page"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_home_group_list_title"
app:tabIndicatorColor="@color/white"
app:tabIndicatorFullWidth="false"
app:tabSelectedTextColor="@color/bottomTextColor"
app:tabTextAppearance="@android:style/TextAppearance.Holo"
app:tabTextColor="@color/defaultTextViewColor" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/vp_group_page"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="horizontal"
android:paddingTop="6dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tab_layout_group"
app:layout_constraintVertical_weight="1" />
-
创建 Adapter
Adapter 需要继承 FragmentStateAdapter
public class LiveViewPagerAdapter extends FragmentStateAdapter {
private ArrayList<Fragment> fragmentList;
public LiveViewPagerAdapter(@NonNull Fragment fragment) {
super(fragment);
}
public LiveViewPagerAdapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
public LiveViewPagerAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
super(fragmentManager, lifecycle);
}
public void setFragmentList(ArrayList<Fragment> fragmentList) {
this.fragmentList = fragmentList;
}
......
}
-
重写 createFragment 和 getItemCount 方法
需要在 Adapter 中重写这两个方法
@NonNull
@Override
public Fragment createFragment(int position) {
// 返回Fragment
return fragmentList.get(position);
}
@Override
public int getItemCount() {
// 获取Fragment数量
return fragmentList.size();
}
-
Activity / Fragment 中的使用
这里以 Fragment 为例,在父 Fragment 中使用,在 initData 方法中设置 Fragment List,在 initView 中 setAdapter。
和我们在 RecyclerView 中设置 Adapter 和数据没有区别,只是这里的数据是 Fragment。
值得注意的是:设置页面切换时 TabLayout 样式有两种方式。请注意看代码注释
第一种主要是使用 ViewPager2 的 registerOnPageChangeCallback 方法来控制
第二种则是通过 new TabLayoutMediator 来关联 TabLayout 和 ViewPager2 进行控制,该方式和 ViewPager 的 setupWithViewPager 基本一致,可以算得上是升级到 ViewPager2 后的替代方法。
public class LiveFragment extends Fragment {
private FragmentLiveBinding binding;
private ArrayList<Fragment> fragmentArrayList;
private final int LIVE_RECOMMEND = 0;
private final int LIVE_FOLLOW = 1;
......
@Override
public void onStart() {
super.onStart();
initData();
initView();
}
private void initData(){
fragmentArrayList = new ArrayList<>();
fragmentArrayList.add(LIVE_RECOMMEND, new LiveRecommendFragment());
fragmentArrayList.add(LIVE_FOLLOW, new LiveFollowFragment());
}
// 以下是第一种方式
private void initView(){
LiveViewPagerAdapter liveViewPagerAdapter = new LiveViewPagerAdapter(this);
liveViewPagerAdapter.setFragmentList(fragmentArrayList);
binding.vpLiveContainer.setAdapter(liveViewPagerAdapter);
binding.vpLiveContainer.setCurrentItem(lastPage, false);
}
private void initEvent() {
binding.vpLiveContainer.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
if (position == LIVE_FOLLOW) {
binding.tvLiveFollow.setTextColor(mContext.getColor(R.color.white));
binding.tvLiveRecommend.setTextColor(mContext.getColor(R.color.defaultTextColor));
} else {
binding.tvLiveFollow.setTextColor(mContext.getColor(R.color.defaultTextColor));
binding.tvLiveRecommend.setTextColor(mContext.getColor(R.color.white));
}
lastPage = position;
}
});
}
// 这里是第二种方式
private void initView() {
GroupTypeViewPagerAdapter groupTypeAdapter = new GroupTypeViewPagerAdapter(this);
groupTypeAdapter.setFragments(fragments);
groupListBinding.vpGroupPage.setAdapter(groupTypeAdapter);
new TabLayoutMediator(groupListBinding.tabLayoutGroup, groupListBinding.vpGroupPage, (tab, position) -> {
// 可以根据positions设置Tab样式
if (position == 0) {
tab.setText(R.string.homeGroupMine);
} else if (position == 1) {
tab.setText(R.string.homeGroupInvited);
}
}).attach();
}
}
这样关于 ViewPager2 的使用就 OK 了。两者都清楚了,下面说明以下两者区别
ViewPager 和 ViewPager2 的区别
-
在布局方面:
ViewPager 允许有子 View
而 ViewPager2 不允许有子 View 存在
-
在继承方面:
ViewPager 的 Adapter 继承 FragmentStatePagerAdapter
而 ViewPager2 的 Adapter 继承 FragmentStateAdapter
-
在设置 Fragment 方面:
ViewPager 可以直接分别设置 FragmentList 和 FragmentTitleList
而 ViewPager2 则是只能设置 FragmentList(也可能是我没发现,如果有类似 FragmentStatePagerAdapter 和 getPageTitle() 方法的烦请告知,谢谢)
-
在关联及监听方面:
ViewPager 只需要简单的设置 Adapter 或者通过 TabLayout 的 setupWithViewPager(ViewPager) 方法进行关联。
而 ViewPager2 则是需要 new TabLayoutMediator() 方法或者通过 ViewPager2 的监听回调 registerOnPageChangeCallback() 来实现
本篇关于 ViewPager 和 ViewPager2 的 Blog 到此结束,如果有错误,请斧正。