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中的滑动都是瞬时滑动。没有任何的过渡效果.


猜你喜欢

转载自blog.csdn.net/qq_31214937/article/details/52366160