摘要android
今天和你們分享一下如何定製一個能夠循環滑動的viewpager。其實今天更重要的提供一種組件化思想,固然你能夠理解爲面向對象思想。git
吐槽一下網上流行的實現方式吧(爲了方便說明,下文稱之爲方式A),方式A是重寫adapter的getCount方法,返回一個很大的數(值爲max),adapter中的getView方法中的position從新根據實際數量取模,把viewpager設置在max二分之一的位置。由於這個值很大因此基本不可能滑動到position=0或者position=max的位置,不過確切來講這並非無限循環,採用腳本之類的應該能夠滑動到邊界(沒有試驗過)。github
咱們的需求設計模式
快速把以前viewpager相關的代碼改爲無限循環。ide
這個需求很簡單就是在已有的代碼上完成無限循環。固然你能夠根據方式A來完成,它是經過適配器來完成無限循環的,不過這種方式你須要改的代碼並很多,畢竟你得改適配器。組件化
本文須要提供的方式B就登場了,好處在於不用改你的adapter,只須要把你的viewpager改爲本文中的組件CycleViewPager就能夠了,其餘的都不用改。this
原理spa
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)。設計
直接上代碼code
1 package com.vane.widget.cycleviewpager; 2 3 import android.content.Context; 4 import android.database.DataSetObserver; 5 import android.support.v4.view.PagerAdapter; 6 import android.support.v4.view.ViewPager; 7 import android.util.AttributeSet; 8 import android.view.View; 9 import android.view.ViewGroup; 10 11 public class CycleViewPager extends ViewPager { 12 13 private InnerPagerAdapter mAdapter; 14 15 public CycleViewPager(Context context) { 16 super( context); 17 setOnPageChangeListener( null); 18 } 19 20 public CycleViewPager(Context context, AttributeSet attrs) { 21 super( context, attrs); 22 setOnPageChangeListener( null); 23 } 24 25 @Override 26 public void setAdapter(PagerAdapter arg0) { 27 mAdapter = new InnerPagerAdapter( arg0); 28 super.setAdapter( mAdapter); 29 setCurrentItem( 1); 30 } 31 32 @Override 33 public void setOnPageChangeListener(OnPageChangeListener listener) { 34 super.setOnPageChangeListener( new InnerOnPageChangeListener( listener)); 35 } 36 37 private class InnerOnPageChangeListener implements OnPageChangeListener { 38 39 private OnPageChangeListener listener; 40 private int position; 41 42 public InnerOnPageChangeListener(OnPageChangeListener listener) { 43 this.listener = listener; 44 } 45 46 @Override 47 public void onPageScrollStateChanged(int arg0) { 48 if(null != listener) { 49 listener.onPageScrollStateChanged( arg0); 50 } 51 if(arg0 == ViewPager.SCROLL_STATE_IDLE) { 52 if(position == mAdapter.getCount() - 1) { 53 setCurrentItem( 1, false); 54 } 55 else if(position == 0) { 56 setCurrentItem( mAdapter.getCount() - 2, false); 57 } 58 } 59 } 60 61 @Override 62 public void onPageScrolled(int arg0, float arg1, int arg2) { 63 if(null != listener) { 64 listener.onPageScrolled( arg0, arg1, arg2); 65 } 66 } 67 68 @Override 69 public void onPageSelected(int arg0) { 70 position = arg0; 71 if(null != listener) { 72 listener.onPageSelected( arg0); 73 } 74 } 75 } 76 77 private class InnerPagerAdapter extends PagerAdapter { 78 79 private PagerAdapter adapter; 80 81 public InnerPagerAdapter(PagerAdapter adapter) { 82 this.adapter = adapter; 83 adapter.registerDataSetObserver( new DataSetObserver() { 84 85 @Override 86 public void onChanged() { 87 notifyDataSetChanged(); 88 } 89 90 @Override 91 public void onInvalidated() { 92 notifyDataSetChanged(); 93 } 94 95 }); 96 } 97 98 @Override 99 public int getCount() { 100 return adapter.getCount() + 2; 101 } 102 103 @Override 104 public boolean isViewFromObject(View arg0, Object arg1) { 105 return adapter.isViewFromObject( arg0, arg1); 106 } 107 108 @Override 109 public Object instantiateItem(ViewGroup container, int position) { 110 if(position == 0) { 111 position = adapter.getCount() - 1; 112 } 113 else if(position == adapter.getCount() + 1) { 114 position = 0; 115 } 116 else { 117 position -= 1; 118 } 119 return adapter.instantiateItem( container, position); 120 } 121 122 @Override 123 public void destroyItem(ViewGroup container, int position, Object object) { 124 adapter.destroyItem( container, position, object); 125 } 126 127 } 128 }
如何使用
使用方法和viewPager是同樣同樣的,你就認爲是viewpager來使用就能夠了。源碼你能夠在github上取https://github.com/vanezkw/cycleviewpager.git
總結
源碼中你們也都看到了沒有什麼特別的其實就是平時講的設計模式。以前提到的方式A我的認爲並不徹底是面向對象的方式,這個固然也看你們如何理解。
若是文中有任何疑問或者不妥之處歡迎留言交流。在此也留下QQ羣311536202,歡迎交流。