【Android開發日記】左右滑動刷新界面的思路記錄 ViewPager GestureDetector

需求:

通過左右滑動刷新ViewPager的內容,要求往右前進,往左後退,除非遇到數據兩個端點否則不會間斷。

記錄一下我的處理過程,前後一共試用了4種方法:


方法一:ViewPager(10個page)

左右滑動處理:ViewPager中添加10個page,都是一個Fragment的複用,當滑動到最後一個界面時,跳轉到第一個page。實現循環滑動。

數據處理:

內存常駐10組數據。

第一次加載:初次加載10條數據,分別佈局到10個page上。

更新數據:每當向右滑動滑動到第10個page時,自動加載新的一組數據。每當向左滑動到第1個page時,加載一組新的數據。

當然,加載的數據可以從網上下載或者從本地數據表或文件加載。

思路介紹:

1.10張page的ViewPage只用在首尾加載數據,中間可以保證流暢滑動加載。

2.使用setCurrentItem();進行跳轉,實現循環滑動的效果。即只要有數據,向左向右可以無限拖動。

3,ViewPager滑動時的默認動畫是可以看到下一張的縮影的,而我們的數據已經佈局到每一個page上了,因此縮影上有數據。

出現的bug:

1.使用setCurrentItem();從最後一張跳到第一張時,不是一下跳到的,而是遍歷了從0-9張,可以使用下面的代碼來遮蓋這個效果,優化動畫:

//控制跳轉速度
			public class FixedSpeedScroller extends Scroller {  
			    private int mDuration = 0;  
			  
			    public FixedSpeedScroller(Context context) {  
			        super(context);  
			    }  
			  
			    public FixedSpeedScroller(Context context, Interpolator interpolator) {  
			        super(context, interpolator);  
			    }  
			  
			    @SuppressLint("NewApi")
				public FixedSpeedScroller(Context context, Interpolator interpolator, boolean flywheel) {  
			        super(context, interpolator, flywheel);  
			    }  
			  
			  
			    @Override  
			    public void startScroll(int startX, int startY, int dx, int dy, int duration) {  
			        super.startScroll(startX, startY, dx, dy, mDuration);  
			    }  
			  
			    @Override  
			    public void startScroll(int startX, int startY, int dx, int dy) {  
			        super.startScroll(startX, startY, dx, dy, mDuration);  
			    }  
			}
			
			//* 設置ViewPager的滑動速度 
		    // *  
		    // * */  
		    private void setViewPagerScrollSpeed( ){  
		        try {  
		            Field mScroller = null;  
		            mScroller = ViewPager.class.getDeclaredField("mScroller");  
		            mScroller.setAccessible(true);   
		            FixedSpeedScroller scroller = new FixedSpeedScroller( vp.getContext( ) );  
		            mScroller.set( vp, scroller);  
		        }catch(NoSuchFieldException e){  
		              
		        }catch (IllegalArgumentException e){  
		              
		        }catch (IllegalAccessException e){  
		              
		        }  
		    }

2.由於是控制在前進或者退後的最後一張加載數據:即向左滑動,index+1,在第10張時更新數據;向右滑動,index-1,在第1張時更新數據。

但是如果你是index+1 到達最後一張,更新了下一組的數據(第2組 10-19),但是這時又往回拖動,希望還是顯示的第一組(0-9),就會發現顯示的是內存中剛加載的第二組(10-19)。同樣,在後退時也存在這樣一個bug。

3.10個page太多,佔用緩存。


方法二:ViewPager(3個page)

這時請教了羣裏的少年們得到的方法,謝謝。

使用了3個page的ViewPager,複用同一個Fragment。

左右滑動:

雖然使用了3個page的ViewPager,用戶看到的始終是第2個即中間的那個page。

當向左滑動,本來會跳到第3個page,使用setCurrentItem(1);跳回去。當向右滑動,本來會轉到第1個page,使用setCurrentItem(1);跳回去。

數據處理:

在使用了setCurrentItem(1);方法後更新數據。


思路:

1.是用戶看到的始終是第2個page,這樣解決了循環滑動的問題。

bug:

1.滑動page時看到的下一張的縮影是空白的。

2,內存中如果放置一組數據,還是無法預判加載一組新數據後用戶的操作。


方法三:ViewPager +  GestureDetector

這時我想利用Gesture是否可以通過用戶的手勢事先預判用戶的滑動方向呢?這樣根據手勢來決定加載哪一組數據進入內存。

我在方法二的基礎上使用了GestureDetector,這時候出現了手勢事件處理的衝突問題

Viewpager是子控件, GestureDetector是綁定在父控件上的,改來改去,有時候只有ViewPager拿到手勢事件,有時候只有父控件拿到手勢事件。

突然我想到,既然能通過手勢來判斷左右動作,爲什麼不跳過ViewPager這個梗呢?只使用一個佈局,每次通過手勢判斷更新數據?


方法四: GestureDetector

只使用一個GestureDetector,通過手勢判斷前進或者後退。

但是數據處理上,一次加載10組數據進內存的辦法我放棄了。因爲即使使用手勢判斷,還是有bug,比如說現在顯示的10個數據中的組後一組,手勢判斷知道要前進,那麼會加載新的10個數據進內存,這時候如果再後退,會又加載10條舊的數據進內存。

因此我在數據處理上將數據放在SQLite表中,每次手勢判斷到向左或向右,就去數據表中加載對應的一條數據出來更新佈局。實驗證明,從數據表中select一條數據,然後即使根據數據再去sd卡上讀一張圖片,然後將文字和圖片佈局到界面上,效果還是不錯的。現在的手機cpu完全可以應對。

在程序中記錄當前的信息編號index以及本地表中最大的信息編號maxindex,然後在合適的時機下載若干組數據到本地存入SQLite數據表,這樣的話,每次滑動後臺執行的
動作就是讀表然後佈局。


四種方法中方法四是我現在採用的,當然不一定是最好的處理辦法。

寫的比較亂,希望對大家有所啓發,看不清楚可以在評論中指出,當然如果你有更好的辦法請分享給我!





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章