Android中scrollView的滑動原理
android中所有View都是可以滑動的,其實所有的View都有兩套座標系,一個是指定View位置的X,Y,另一對則是指定View滑動座標系,mScrollX和mScrollY,兩對座標系統是完全獨立的,即X,Y座標的改變不會影響mScrollX和mScrollY,反之也成立。
scrollTo(int x, int y) 是將View中內容滑動到相應的位置,參考的座標系原點為parent View的左上角。
mScrollX和mScrollY是View類中專門用於記錄滑動位置的變數。這兩個函式最終呼叫onScrollChanged()函式。
android的滑動原理就是:通過呼叫scrollTo(),
當我們呼叫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(this, null);
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中的滑動都是瞬時滑動。沒有任何的過渡效果.