GeorgeYang'Blog

my technology blog

支持内容不重复的无限左右滑动的InfiniteScrollViewPager

阅读:281 创建时间:16-06-15 12:40:45 tags:android,viewpager

以前做app的时候,写过一个首页广告轮播viewpager自定义控件,viewpager的无限翻页原理就是:原本应该第一页的数据,在前面加一页数据,这个前面插入的界面,显示原本应该在最后一页的界面,即和最后一项一样,同时最后面也要加入一页数据,用于显示原本第一页的数据,前后都加入一个copy出来的界面,左滑到最左,右滑到最右的时候,使用setCurrentItem(index,false)在后台把界面重置,具体代码如下:

 public void setLists(List<String> pictureUrls) {
    pictureUrls.add(0,pictureUrls.get(pictureUrls.size()-1));
    pictureUrls.add(pictureUrls.get(0));
 }


 @Override
 public void onPageScrollStateChanged(int stat) {
     if (stat == 0) {// 滑动停止
         int currIndex = getCurrentItem();
        int tagIndex = currIndex;
        if (currIndex == 0) {
            tagIndex = urls.size();
        } else if (currIndex == urls.size() + 1) {
            tagIndex = 1;
        }
        if (currIndex != tagIndex) {
            setCurrentItem(tagIndex, false);
        }
     }
 }

这样是实现了viewpager无限循环,但是最多只能有list.size()种内容,由于有些时候项目需要无限多种item,如果采用网上所谓的adapter设置getCount return Integer.MAX_VALUE;的话,不能左边无限话,只是从左边开始向右滑动,如果你用的是Integer.MAX_VALUE的方法博客出处,那么你需要setCurrentItem:Integer.MAX_VALUE/2,那么程序就会奔溃。


由于种种问题的出现,所以我觉得造个轮子,原理还是和上面的一样,不同的是增加类似于listview的重用机制,定义一个getview方法创建view,再定义一个bindview方法,传index,把数据绑定在view上,具体代码如下:

 package cn.georgeyang.widget;

 /**
  * 无限滚动的viewpager,必须item都相同
  * Created by george.yang on 16/6/14.
  */
 public class InfiniteScrollViewPager extends ViewPager {
     public InfiniteScrollViewPager(Context context) {
         super(context);
         init(context);
     }

     public InfiniteScrollViewPager(Context context, AttributeSet attrs) {
         super(context, attrs);
         init(context);
     }

     private int currIndex = 0;
     private int lastIndex ;
     private Context mContext;
     private void init(Context context) {
         this.mContext = context;
 //        super.setPageTransformer(true, new AccordionTransformer());
         super.setOnPageChangeListener(new OnPageChangeListener() {

             @Override
             public void onPageSelected(int index) {
                 if (index==lastIndex+1){
                     currIndex ++;
                 } else if (index==lastIndex-1) {
                     currIndex --;
                 }

                 lastIndex = index;

                 if (mListener!=null) {
                     mListener.onPageSelected(currIndex);
                 }
             }

             @Override
             public void onPageScrolled(int arg0, float arg1, int arg2) {
                 if (mListener!=null) {
                     mListener.onPageScrolled(arg0, arg1, arg2);
                 }
             }

             @Override
             public void onPageScrollStateChanged(int stat) {
                 if (stat == 0) {// 滑动停止
                     int index = getCurrentItem();
                     if (index == 0) {
                         reBindView(currIndex-5);
                         setCurrentItem(3, false);
                     } else if (index == 4) {
                         reBindView(currIndex-1);
                         setCurrentItem(1, false);
                     }
                 }

                 if (mListener!=null) {
                     mListener.onPageScrollStateChanged(stat);
                 }
             }
         });
     }

     private OnPageChangeListener mListener;

     @Override
     public void setOnPageChangeListener(OnPageChangeListener listener) {
         mListener = listener;
     }



     private List<View> views;
     private ViewBuilder viewBuilder;
     public void setViewBuilder(ViewBuilder viewBuilder) {
         if (viewBuilder!=null) {
             this.viewBuilder = viewBuilder;
             views = new ArrayList<>();
             for (int i=0;i<3;i++) {
                 views.add(viewBuilder.buildView(mContext,i));
             }
             views.add(0,viewBuilder.buildView(mContext,-1));
             views.add(viewBuilder.buildView(mContext,4));

             reBindView(-1);

             ADViewPagerAdapter adapter = new ADViewPagerAdapter(views);
             this.setAdapter(adapter);
             setCurrentItem(1);
             lastIndex = 0;
         }
     }

     @Override
     public void setCurrentItem(int item) {
         super.setCurrentItem(item);
     }

     private void reBindView (int zeroIndex) {
         if (viewBuilder==null) return;
         for (int i=0;i<5;i++) {
             viewBuilder.bindView(mContext,views.get(i),zeroIndex+i);
         }
     }
 }


 public interface ViewBuilder {
     View buildView(Context context,int index,Object... arg);
     void bindView (Context context,View view,int index);
 }

默认显示的index是0,可以滑动到Integer.MAX_VALUE或Integer.MIN_VALUE

enjoy it