导航

自定义循环滑动的viewpager

Posted on 2017-06-16 01:27  Young哥哥  阅读(87)  评论(0编辑  收藏  举报

自定义循环滑动的viewpager

摘要

今天和大家分享一下如何定制一个可以循环滑动的viewpager。其实今天更重要的提供一种组件化思想,当然你可以理解为面向对象思想。

吐槽一下网上流行的实现方式吧(为了方便说明,下文称之为方式A),方式A是重写adapter的getCount方法,返回一个很大的数(值为 max),adapter中的getView方法中的position重新根据实际数量取模,把viewpager设置在max二分之一的位置。因为这个 值很大所以基本不可能滑动到position=0或者position=max的位置,不过确切来说这并不是无限循环,采用脚本之类的应该可以滑动到边界 (没有试验过)。

 

我们的需求

快速把之前viewpager相关的代码改成无限循环。

这个需求很简单就是在已有的代码上完成无限循环。当然你可以根据方式A来完成,它是通过适配器来完成无限循环的,不过这种方式你需要改的代码并不少,毕竟你得改适配器。

本文需要提供的方式B就登场了,好处在于不用改你的adapter,只需要把你的viewpager改成本文中的组件CycleViewPager就可以了,其他的都不用改。

 

原理

CycleViewPager继承ViewPager。当向右翻页(文中指的向右翻页是指手指由右向左滑,向左翻页反之),数据滑动到最后一条数据 时调用setCurrentItem(0)返回第一条,当向左翻页,数据滑动到第一条数据时setCurrentItem(getCount()-1)返 回到最后一条数据。在设置数据的时候需要多生成两条数据,比如原始数据是[a,b,c,d,e],那么生成的数据为[e,a,b,c,d,e,a],原始 数据第一条前面加了最后一条数据e,原始数据的最后一条的后面加了原始数据的第一条数据a。从a滑到e时,继续向右翻页那么就到了数据a(最右边的那个 a),停止滑动时调用setCurrentItem(1)返回第一条数据a(最左边的那个a);从e滑动到a时,继续向左翻页那么就到了数据e(做左边的 那个e),停止滑动时调用setCurrentItem(5)。

 

直接上代码

复制代码
  1package com.vane.widget.cycleviewpager;
  2  3import android.content.Context;
  4import android.database.DataSetObserver;
  5import android.support.v4.view.PagerAdapter;
  6import android.support.v4.view.ViewPager;
  7import android.util.AttributeSet;
  8import android.view.View;
  9import android.view.ViewGroup;
 10 11publicclass CycleViewPager extends ViewPager {
 12 13private InnerPagerAdapter mAdapter;
 14 15public CycleViewPager(Context context) {
 16super( context);
 17         setOnPageChangeListener( null);
 18    }
 19 20public CycleViewPager(Context context, AttributeSet attrs) {
 21super( context, attrs);
 22         setOnPageChangeListener( null);
 23    }
 24 25    @Override
 26publicvoid setAdapter(PagerAdapter arg0) {
 27         mAdapter = new InnerPagerAdapter( arg0);
 28super.setAdapter( mAdapter);
 29         setCurrentItem( 1);
 30    }
 31 32    @Override
 33publicvoid setOnPageChangeListener(OnPageChangeListener listener) {
 34super.setOnPageChangeListener( new InnerOnPageChangeListener( listener));
 35    }
 36 37privateclass InnerOnPageChangeListener implements OnPageChangeListener {
 38 39private OnPageChangeListener listener;
 40privateint position;
 41 42public InnerOnPageChangeListener(OnPageChangeListener listener) {
 43this.listener = listener;
 44        }
 45 46        @Override
 47publicvoid onPageScrollStateChanged(int arg0) {
 48if(null != listener) {
 49                listener.onPageScrollStateChanged( arg0);
 50            }
 51if(arg0 == ViewPager.SCROLL_STATE_IDLE) {
 52if(position == mAdapter.getCount() - 1) {
 53                     setCurrentItem( 1, false);
 54                }
 55elseif(position == 0) {
 56                     setCurrentItem( mAdapter.getCount() - 2, false);
 57                }
 58            }
 59        }
 60 61        @Override
 62publicvoid onPageScrolled(int arg0, float arg1, int arg2) {
 63if(null != listener) {
 64                listener.onPageScrolled( arg0, arg1, arg2);
 65            }
 66        }
 67 68        @Override
 69publicvoid onPageSelected(int arg0) {
 70             position = arg0;
 71if(null != listener) {
 72                listener.onPageSelected( arg0);
 73            }
 74        }
 75    }
 76 77privateclass InnerPagerAdapter extends PagerAdapter {
 78 79private PagerAdapter adapter;
 80 81public InnerPagerAdapter(PagerAdapter adapter) {
 82this.adapter = adapter;
 83             adapter.registerDataSetObserver( new DataSetObserver() {
 84 85                @Override
 86publicvoid onChanged() {
 87                    notifyDataSetChanged();
 88                }
 89 90                @Override
 91publicvoid onInvalidated() {
 92                    notifyDataSetChanged();
 93                }
 94 95            });
 96        }
 97 98        @Override
 99publicint getCount() {
100return adapter.getCount() + 2;
101        }
102103        @Override
104publicboolean isViewFromObject(View arg0, Object arg1) {
105return adapter.isViewFromObject( arg0, arg1);
106        }
107108        @Override
109public Object instantiateItem(ViewGroup container, int position) {
110if(position == 0) {
111                 position = adapter.getCount() - 1;
112            }
113elseif(position == adapter.getCount() + 1) {
114                 position = 0;
115            }
116else {
117                 position -= 1;
118            }
119return adapter.instantiateItem( container, position);
120        }
121122        @Override
123publicvoid destroyItem(ViewGroup container, int position, Object object) {
124            adapter.destroyItem( container, position, object);
125        }
126127    }
128 }
复制代码

 

如何使用

使用方法和viewPager是一样一样的,你就认为是viewpager来使用就可以了。源码你可以在github上取https://github.com/vanezkw/cycleviewpager.git

 

总结

源码中大家也都看到了没有什么特别的其实就是平时讲的设计模式。之前提到的方式A个人认为并不完全是面向对象的方式,这个当然也看大家如何理解。