1. 程式人生 > >Android中scrollView的滑動原理

Android中scrollView的滑動原理

android中所有View都是可以滑動的,其實所有的View都有兩套座標系,一個是指定View位置的XY,另一對則是指定View滑動座標系,mScrollXmScrollY,兩對座標系統是完全獨立的,即XY座標的改變不會影響mScrollXmScrollY,反之也成立。

scrollTo(int x, int y) 是將View內容滑動到相應的位置,參考的座標系原點為parent View的左上角。

 mScrollXmScrollYView類中專門用於記錄滑動位置的變數。這兩個函式最終呼叫onScrollChanged()函式。

android的滑動原理就是:通過呼叫scrollTo(),

使的View的滑動座標系發生改變,並儲存在mScrollXmScrollY這兩個成員變數中,我們可以通過getScrollX()getScrollY(),獲取滑動座標值。

當我們呼叫scrollTo(100,0);時,發現View是向左滑動了,傳入一個正數滑動的方向卻是向左,這與我們平常理解的座標軸是相反的,其實並不矛盾,因為滑動座標系本來就與我們平常的座標系統不一樣,呼叫scrollTo方法,最終會執行到以下程式碼:

1. public void invalidate(int l, int t, int r, int b) {    

2.     if (ViewDebug.TRACE_HIERARCHY) {    

3.         ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);    

4.     }    

5.     

6.     if (skipInvalidate()) {    

7.         return;    

8.     }    

9.     if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||    

10.             (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||    

11.             (mPrivateFlags & INVALIDATED) != INVALIDATED) {    

12.         mPrivateFlags &= ~DRAWING_CACHE_VALID;    

13.         mPrivateFlags |= INVALIDATED;    

14.         mPrivateFlags |= DIRTY;    

15.         final ViewParent p = mParent;    

16.         final AttachInfo ai = mAttachInfo;    

17.         //noinspection PointlessBooleanExpression,ConstantConditions    

18.         if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {    

19.             if (p != null && ai != null && ai.mHardwareAccelerated) {    

20.                 // fast-track for GL-enabled applications; just invalidate the whole hierarchy    

21.                 // with a null dirty rect, which tells the ViewAncestor to redraw everything    

22.                 p.invalidateChild(thisnull);    

23.                 return;    

24.             }    

25.         }    

26.         if (p != null && ai != null && l < r && t < b) {    

27.             final int scrollX = mScrollX;    

28.             final int scrollY = mScrollY;    

29.             final Rect tmpr = ai.mTmpInvalRect;    

30.             tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);    

31.             p.invalidateChild(this, tmpr);    

32.         }    

33.     }    

34. }    

看倒數第五行程式碼,更新滑動座標系時,走的是 tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);傳入一個正數後一減,就成了負數,然後就成了向左移動了;View中的滑動都是瞬時滑動。沒有任何的過渡效果.