ViewPager就是每个Pager配置不同的View,通过左右滑动可以切换View。介绍几种我用过的ViewPager的用法。
一、常规用法
左右滑动的View,使用Adapter配置View即可。
页面xml代码
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager1"
android:layout_width="match_parent"
android:background="#999999"
android:layout_height="150dp"/>
viewPager的View里面就是放了一个TextView,adapter实现如下
public class RegularPagerAdapter extends PagerAdapter {
private Context context;
private List<String> dataList;
public RegularPagerAdapter(Context context, List<String> datas) {
this.context = context;
this.dataList = datas;
}
@Override
public int getCount() {
return dataList.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
return view == o;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
// super.destroyItem(container, position, object);必须删除,否则报错
container.removeView((View) object);
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup viewGroup, int position) {
ItemPagerRegularBinding binding = DataBindingUtil.bind(LayoutInflater.from(context).inflate(R.layout.item_pager_regular, viewGroup, false));
binding.tvName.setText(dataList.get(position));
viewGroup.addView(binding.getRoot());
return binding.getRoot();
}
}
activity中使用
private void setRegularPager() {
List<String> dataList = new ArrayList<>();
for (int i = 0; i < 4; i++) {
dataList.add("这是我的第" + (i + 1) + "个Pager");
}
RegularPagerAdapter adapter = new RegularPagerAdapter(this, dataList);
mBinding.viewPager1.setAdapter(adapter);
}
页面实现效果

二、上下滑动的ViewPager
ViewPager默认的滑动方向是左右滑动,但是有时候需要实现上下滑动的方式。那就继承ViewPager实现一个VerticalViewPager。这个代码是在网上找的别人实现的,可以拿过来直接用。
public class VerticalViewPager extends ViewPager {
public VerticalViewPager(Context context) {
super(context);
init();
}
public VerticalViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// 最重要的设置,将viewpager翻转
setPageTransformer(true, new VerticalPageTransformer());
// 设置去掉滑到最左或最右时的滑动效果
setOverScrollMode(OVER_SCROLL_NEVER);
}
private class VerticalPageTransformer implements PageTransformer {
@Override
public void transformPage(View view, float position) {
if (position < -1) { // [-Infinity,-1)
// 当前页的上一页
view.setAlpha(0);
} else if (position <= 1) { // [-1,1]
view.setAlpha(1);
// 抵消默认幻灯片过渡
view.setTranslationX(view.getWidth() * -position);
//设置从上滑动到Y位置
float yPosition = position * view.getHeight();
view.setTranslationY(yPosition);
} else { // (1,+Infinity]
// 当前页的下一页
view.setAlpha(0);
}
}
}
/**
* 交换触摸事件的X和Y坐标
*/
private MotionEvent swapXY(MotionEvent ev) {
float width = getWidth();
float height = getHeight();
float newX = (ev.getY() / height) * width;
float newY = (ev.getX() / width) * height;
ev.setLocation(newX, newY);
return ev;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
swapXY(ev);
return intercepted; //为所有子视图返回触摸的原始坐标
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
return super.onTouchEvent(swapXY(ev));
}
}
我遇到的情况是,本来是写了个Recyclerview实现网格布局实现上下滑动,但是老板说要两排一组,一组一组的滑动,那不就是得改成ViewPager么!这个先上个效果图吧

上面每个小View放的数据是ItemBean,里面属性是name和resId。每个View还都可以点击,或者数据更新改变状态什么的,这个就是直接更新数据源,然后ViewPager的Adapter设置notifyDataSetChanged()即可。
viewPager的Adapter
public class CategoryPagerAdapter extends PagerAdapter {
private Context context;
private ArrayList<ArrayList<ItemBean>> datas;
private int spanCount;
private OnPageItemClickListener listener;
public CategoryPagerAdapter(Context context, ArrayList<ArrayList<ItemBean>> datas, int spanCount, OnPageItemClickListener listener) {
this.context = context;
this.datas = datas;
this.spanCount = spanCount;
this.listener = listener;
}
public void updateData(ArrayList<ArrayList<ItemBean>> datas, int spanCount){
this.datas.clear();
this.datas.addAll(datas);
this.spanCount = spanCount;
notifyDataSetChanged();
}
@Override
public int getCount() {
return datas.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
return view == o;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
// super.destroyItem(container, position, object);必须删除,否则报错
container.removeView((View) object);
}
@Override
public int getItemPosition(@NonNull Object object) {
return POSITION_NONE;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup viewGroup, int page) {
ItemPagerCategoryBinding binding = DataBindingUtil.bind(LayoutInflater.from(context).inflate(R.layout.item_pager_category, viewGroup, false));
//recyclerview设置网格布局
GridLayoutManager gridLayoutManager = new GridLayoutManager(context, spanCount);
binding.rvPager.setLayoutManager(gridLayoutManager);
binding.rvPager.getItemAnimator().setChangeDuration(0);
ItemAdapter buttonsAdapter = new ItemAdapter(context, datas.get(page), (position, bean) -> listener.onItemClick(page, position, bean));
buttonsAdapter.setHasStableIds(true);
binding.rvPager.setAdapter(buttonsAdapter);
viewGroup.addView(binding.getRoot());
return binding.getRoot();
}
public interface OnPageItemClickListener {
void onItemClick(int page, int position, ItemBean bean);
}
}
页面xml
<com.example.myapplication.viewpager.VerticalViewPager
android:id="@+id/viewPager2"
android:layout_width="match_parent"
android:layout_height="112dp"
android:layout_marginTop="10dp"/>
activity使用
private void setCategoryPager() {
ArrayList<ArrayList<ItemBean>> dataList = getCategoryPagerData(8);
CategoryPagerAdapter adapter = new CategoryPagerAdapter(this, dataList, 4, (page, position, bean) -> {
Toast.makeText(this, "点击:"+bean.getName() +",位置:"+position,Toast.LENGTH_SHORT).show();
});
mBinding.viewPager2.setAdapter(adapter);
}
private ArrayList<ArrayList<ItemBean>> getCategoryPagerData(int pageCount) {
ArrayList<ArrayList<ItemBean>> dataList = new ArrayList<>();//viewPager的数据源
ArrayList<ItemBean> list = new ArrayList<>();//recyclerview的数据源
list.add(new ItemBean("箱包", R.mipmap.icon_bag));
list.add(new ItemBean("美妆", R.mipmap.icon_beauty));
list.add(new ItemBean("图书", R.mipmap.icon_book));
list.add(new ItemBean("电子", R.mipmap.icon_computer));
list.add(new ItemBean("厨具", R.mipmap.icon_cooking));
list.add(new ItemBean("饮品", R.mipmap.icon_drink));
list.add(new ItemBean("水果", R.mipmap.icon_fruits));
list.add(new ItemBean("医药", R.mipmap.icon_medicine));
list.add(new ItemBean("母婴", R.mipmap.icon_mother_and_baby));
list.add(new ItemBean("户外", R.mipmap.icon_outdoors));
list.add(new ItemBean("鞋子", R.mipmap.icon_shoes));
list.add(new ItemBean("女装", R.mipmap.icon_skirt));
list.add(new ItemBean("小家电", R.mipmap.icon_small_appliances));
list.add(new ItemBean("零食", R.mipmap.icon_snacks));
list.add(new ItemBean("男装", R.mipmap.icon_t_shirt));
list.add(new ItemBean("玩具", R.mipmap.icon_toys));
list.add(new ItemBean("蔬菜", R.mipmap.icon_vegetables));
list.add(new ItemBean("风车", R.mipmap.icon_windmill));
int bSize = list.size();
int pageSize = bSize / pageCount + (bSize % pageCount == 0 ? 0 : 1);
for (int i = 0; i < pageSize; i++) {
ArrayList<ItemBean> itemBeans = new ArrayList<>();
int length = pageCount;
if (pageCount > bSize - i * pageCount) {
length = bSize - i * pageCount;
}
for (int j = i * pageCount; j < i * pageCount + length; j++) {
itemBeans.add(list.get(j));
}
dataList.add(itemBeans);
}
return dataList;
}
getCategoryPagerData(int pageCount)这是数据源处理,pageCount是一个ViewPager里面放几个小View,如果横竖屏切换这个pageCount和recyclerview的spanCount就需要修改,spanCount=PageCount/2。本来ArrayList<ItemBean> list是recyclerview的数据源,改成ArrayList<ArrayList<ItemBean>> dataList的ViewPager的数据源,根据pageCount把list放到dataList里面去。
当然,如果需要左右滑动的效果,直接使用ViewPager就可以了。
三、ViewPager+Fragment
很多分步骤或者分页的需求,都是顶部几个按钮,点击不同的按钮下面展示不同的按钮,如下图

上面是RadioGroup,下面是ViewPager嵌套的Fragment。这种的ViewPager不需要左右滑动,可是写一个不滑动的NoScrollViewPager,Fragment里面一般放的是Recyclerview或者其他任何视图。这个也很简单,直接贴页面代码吧
xml
<?xml version="1.0" encoding="utf-8"?>
<layout>
<LinearLayout 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"
android:orientation="vertical">
<RadioGroup
android:id="@+id/rg_page"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:paddingHorizontal="20dp"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_config"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_weight="1"
android:gravity="center"
android:button="@null"
android:checked="true"
android:background="@drawable/selector_check_btn"
android:text="推荐"
android:textSize="16dp"
android:textColor="@drawable/text_button_checked"/>
<RadioButton
android:id="@+id/rb_image"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_weight="1"
android:layout_marginHorizontal="10dp"
android:gravity="center"
android:button="@null"
android:background="@drawable/selector_check_btn"
android:text="必囤"
android:textSize="16dp"
android:textColor="@drawable/text_button_checked"/>
<RadioButton
android:id="@+id/rb_video"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_weight="1"
android:gravity="center"
android:button="@null"
android:background="@drawable/selector_check_btn"
android:text="好物"
android:textSize="16dp"
android:textColor="@drawable/text_button_checked"/>
</RadioGroup>
<com.example.myapplication.viewpager.NoScrollViewPager
android:id="@+id/viewPager3"
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/btn_create" />
</LinearLayout>
</layout>
activity页面
private PagerFragment fragment1;
private PagerFragment fragment2;
private PagerFragment fragment3;
private List<Fragment> fgList;
private void setFragmentPager(){
fragment1 = new PagerFragment(1);
fragment2 = new PagerFragment(2);
fragment3 = new PagerFragment(3);
fgList = new ArrayList<>();
fgList.add(fragment1);
fgList.add(fragment2);
fgList.add(fragment3);
mBinding.viewPager3.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return fgList.get(position);
}
@Override
public int getCount() {
return fgList.size();
}
});
selectPage(0);
mBinding.rgPage.setOnCheckedChangeListener((radioGroup, checkedId) -> {
if (checkedId == mBinding.rbConfig.getId()){
selectPage(0);
}else if (checkedId == mBinding.rbImage.getId()){
selectPage(1);
}else if (checkedId == mBinding.rbVideo.getId()){
selectPage(2);
}
});
}
private void selectPage(int index){
mBinding.viewPager3.setCurrentItem(index, false);
}
本文详细介绍了ViewPager的三种使用方式:1) 常规左右滑动;2) 自定义垂直滑动;3) 结合Fragment实现内容切换。通过实例代码展示了如何实现这些功能,包括自定义VerticalViewPager和不滑动的NoScrollViewPager,适用于不同场景的界面布局需求。
9617

被折叠的 条评论
为什么被折叠?



