編輯:關於Android編程
問題描述
在開發時我們可能經常需要使用到ViewPager的onPageScrolled(int position, float offset, int offsetPixels)方法來獲取ViewPager的滾動信息,然而在使用中發現onPageScrolled並不能准確地回調每一個滾動信息,可能會錯過一些信息,在一些手機上甚至連onPageScrolled滾動停止(offset參數為0的狀態)的信息也不會回調。
問題分析
通過閱讀ViewPager的源碼知道,ViewPager的滾動是配合Scroller實現的,而Scroller的實現原理就是在Scroller的動畫時間內不斷的調整View的位置然後重繪布局,而onPageScrolled的回調和view位置的調整是同步的,但是View的重新繪制是耗時的,這也就是說,onPageScrolled的回調頻率和view的重新繪制相關聯,如果手機的性能差一點,View的刷新次數少,那麼onPageScrolled的回調次數也會相對減少。
後來又發現onPageScrolled的最終狀態的回調在部分手機上存在問題,有部手機很卡也能正常回調,有部手機比較流暢卻也沒有回調,所以可能和安卓系統版本有關,於是對比了一下ViewPager在各個版本的實現,發現了問題;我們知道要通過Scroller實現滾動需要實現computeScroll方法,在這個方法裡判斷滾動是否已完成,沒有完成則通過scrollTo方法滾動到相應的位置。下面是ViewPager的實現:
@Override
public void computeScroll() {
if (!mScroller.isFinished() && mScroller.computeScrollOffset()) {
int oldX = getScrollX();
int oldY = getScrollY();
int x = mScroller.getCurrX();
int y = mScroller.getCurrY();
if (oldX != x || oldY != y) {
scrollTo(x, y);
if (!pageScrolled(x)) {
mScroller.abortAnimation();
scrollTo(0, y);
}
}
// Keep on drawing until the animation has finished.
ViewCompat.postInvalidateOnAnimation(this);
return;
}
// Done with scroll, clean up state.
completeScroll(true);
}
可以看到如果mScroller沒有Finished則會通過pageScrolled回調onPageScrolled 並滾動到指定位置,如果已經Finished則調用completeScroll方法完成最終的狀態,我們的問題是onPageScrolled在最終狀態的調用在有些手機上不正常,所以這其中的玄機很可能發生在completeScroll方法中,於是進一步查看completeScroll方法:
private void completeScroll(boolean postEvents) {
boolean needPopulate = mScrollState == SCROLL_STATE_SETTLING;
if (needPopulate) {
// Done with scroll, no longer want to cache view drawing.
setScrollingCacheEnabled(false);
mScroller.abortAnimation();
int oldX = getScrollX();
int oldY = getScrollY();
int x = mScroller.getCurrX();
int y = mScroller.getCurrY();
if (oldX != x || oldY != y) {
scrollTo(x, y);
if (x != oldX) {
pageScrolled(x);
}
}
}
.....省略部分代碼
}
這裡主要注意下面這個判斷,通過查閱各個版本的源碼,發現只有在api23以上才有這個判斷
if (x != oldX) {
pageScrolled(x);
}
而這個判斷就是回調onPageScrolled方法的。所以答案就出來了:假如不是api23的手機,如果scroller已經finish狀態(動畫的時間到),而view還沒來得及完全刷新,就會走到completeScroll方法,而這時api23以下的手機不回回調onPageScrolled方法。
問題總結
ViewPager的onPageScrolled方法比較不可靠,如果有一些比較關鍵的代碼要放在這裡處理最好改用其它方式實現,不然穩定性不高,容易出問題。
由於移動設備物理顯示空間一般有限,不可能一次性的把所有要顯示的內容都顯示在屏幕上。所以各大平台一般會提供一些可滾動的視圖來向用戶展示數據。Android平台框架中為我們提
在最近的兩篇Qt on Android中學習了怎麼使用基礎的JNI以及如何使用外部IDE來管理Qt應用的Java部分。這章呢,我們繼續前進,關注如何擴展我們的
在Android系統API中,有兩個Camera類: android.graphics.Camera android.hardware.Camera 第二個應用於
推薦閱讀:Android如何通過手機獲取驗證碼來完成注冊功能先給大家展示下界面效果圖,感覺滿意,請參考實現代碼。Main.xml源碼<?xml versio