尊重他人勞動成果,轉載請說明出處:http://blog.csdn.net/bingospunky/article/details/44343477java
在該系列文章第四篇。我準備介紹一下viewpager的touch事件處理。android
假設想了解touch和click的那些事,請瀏覽touch事件傳遞系列的第一篇http://blog.csdn.net/bingospunky/article/details/43603397
ide
假設想了解touch事件一步一步傳遞的路線,請瀏覽touch事件傳遞系列的第二篇http://blog.csdn.net/bingospunky/article/details/43735497
post
假設想從源代碼角度什麼理解viewgroup的dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent怎樣實現。請瀏覽touch事件傳遞系列的第二篇http://blog.csdn.net/bingospunky/article/details/44156771學習
源代碼
代碼A:boolean android.support.v4.view.ViewPager.onInterceptTouchEvent(MotionEvent ev)
this
- public boolean onInterceptTouchEvent(MotionEvent ev) {
-
-
-
-
-
-
- final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
-
-
- if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
-
- if (DEBUG) Log.v(TAG, "Intercept done!");
- mIsBeingDragged = false;
- mIsUnableToDrag = false;
- mActivePointerId = INVALID_POINTER;
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- return false;
- }
-
-
-
- if (action != MotionEvent.ACTION_DOWN) {
- if (mIsBeingDragged) {
- if (DEBUG) Log.v(TAG, "Intercept returning true!");
- return true;
- }
- if (mIsUnableToDrag) {
- if (DEBUG) Log.v(TAG, "Intercept returning false!");
- return false;
- }
- }
-
- switch (action) {
- case MotionEvent.ACTION_MOVE: {
-
-
-
-
-
-
-
-
-
- final int activePointerId = mActivePointerId;
- if (activePointerId == INVALID_POINTER) {
-
- break;
- }
-
- final int pointerIndex = MotionEventCompat.findPointerIndex(ev, activePointerId);
- final float x = MotionEventCompat.getX(ev, pointerIndex);
- final float dx = x - mLastMotionX;
- final float xDiff = Math.abs(dx);
- final float y = MotionEventCompat.getY(ev, pointerIndex);
- final float yDiff = Math.abs(y - mInitialMotionY);
- if (DEBUG) Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff);
-
- if (dx != 0 && !isGutterDrag(mLastMotionX, dx) &&
- canScroll(this, false, (int) dx, (int) x, (int) y)) {
-
- mLastMotionX = x;
- mLastMotionY = y;
- mIsUnableToDrag = true;
- return false;
- }
- if (xDiff > mTouchSlop && xDiff * 0.5f > yDiff) {
- if (DEBUG) Log.v(TAG, "Starting drag!");
- mIsBeingDragged = true;
- requestParentDisallowInterceptTouchEvent(true);
- setScrollState(SCROLL_STATE_DRAGGING);
- mLastMotionX = dx > 0 ? mInitialMotionX + mTouchSlop :
- mInitialMotionX - mTouchSlop;
- mLastMotionY = y;
- setScrollingCacheEnabled(true);
- } else if (yDiff > mTouchSlop) {
-
-
-
-
- if (DEBUG) Log.v(TAG, "Starting unable to drag!");
- mIsUnableToDrag = true;
- }
- if (mIsBeingDragged) {
-
- if (performDrag(x)) {
- ViewCompat.postInvalidateOnAnimation(this);
- }
- }
- break;
- }
-
- case MotionEvent.ACTION_DOWN: {
-
-
-
-
- mLastMotionX = mInitialMotionX = ev.getX();
- mLastMotionY = mInitialMotionY = ev.getY();
- mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
- mIsUnableToDrag = false;
-
- mScroller.computeScrollOffset();
- if (mScrollState == SCROLL_STATE_SETTLING &&
- Math.abs(mScroller.getFinalX() - mScroller.getCurrX()) > mCloseEnough) {
-
- mScroller.abortAnimation();
- mPopulatePending = false;
- populate();
- mIsBeingDragged = true;
- requestParentDisallowInterceptTouchEvent(true);
- setScrollState(SCROLL_STATE_DRAGGING);
- } else {
- completeScroll(false);
- mIsBeingDragged = false;
- }
-
- if (DEBUG) Log.v(TAG, "Down at " + mLastMotionX + "," + mLastMotionY
- + " mIsBeingDragged=" + mIsBeingDragged
- + "mIsUnableToDrag=" + mIsUnableToDrag);
- break;
- }
-
- case MotionEventCompat.ACTION_POINTER_UP:
- onSecondaryPointerUp(ev);
- break;
- }
-
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- mVelocityTracker.addMovement(ev);
-
-
-
-
-
- return mIsBeingDragged;
- }
代碼B:boolean android.support.v4.view.ViewPager.onTouchEvent(MotionEvent ev)
- public boolean onTouchEvent(MotionEvent ev) {
- if (mFakeDragging) {
-
-
-
- return true;
- }
-
- if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) {
-
-
- return false;
- }
-
- if (mAdapter == null || mAdapter.getCount() == 0) {
-
- return false;
- }
-
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- mVelocityTracker.addMovement(ev);
-
- final int action = ev.getAction();
- boolean needsInvalidate = false;
-
- switch (action & MotionEventCompat.ACTION_MASK) {
- case MotionEvent.ACTION_DOWN: {
- mScroller.abortAnimation();
- mPopulatePending = false;
- populate();
-
-
- mLastMotionX = mInitialMotionX = ev.getX();
- mLastMotionY = mInitialMotionY = ev.getY();
- mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
- break;
- }
- case MotionEvent.ACTION_MOVE:
- if (!mIsBeingDragged) {
- final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
- final float x = MotionEventCompat.getX(ev, pointerIndex);
- final float xDiff = Math.abs(x - mLastMotionX);
- final float y = MotionEventCompat.getY(ev, pointerIndex);
- final float yDiff = Math.abs(y - mLastMotionY);
- if (DEBUG) Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff);
- if (xDiff > mTouchSlop && xDiff > yDiff) {
- if (DEBUG) Log.v(TAG, "Starting drag!");
- mIsBeingDragged = true;
- requestParentDisallowInterceptTouchEvent(true);
- mLastMotionX = x - mInitialMotionX > 0 ? mInitialMotionX + mTouchSlop :
- mInitialMotionX - mTouchSlop;
- mLastMotionY = y;
- setScrollState(SCROLL_STATE_DRAGGING);
- setScrollingCacheEnabled(true);
-
-
- ViewParent parent = getParent();
- if (parent != null) {
- parent.requestDisallowInterceptTouchEvent(true);
- }
- }
- }
-
- if (mIsBeingDragged) {
-
- final int activePointerIndex = MotionEventCompat.findPointerIndex(
- ev, mActivePointerId);
- final float x = MotionEventCompat.getX(ev, activePointerIndex);
- needsInvalidate |= performDrag(x);
- }
- break;
- case MotionEvent.ACTION_UP:
- if (mIsBeingDragged) {
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
- int initialVelocity = (int) VelocityTrackerCompat.getXVelocity(
- velocityTracker, mActivePointerId);
- mPopulatePending = true;
- final int width = getClientWidth();
- final int scrollX = getScrollX();
- final ItemInfo ii = infoForCurrentScrollPosition();
- final int currentPage = ii.position;
- final float pageOffset = (((float) scrollX / width) - ii.offset) / ii.widthFactor;
- final int activePointerIndex =
- MotionEventCompat.findPointerIndex(ev, mActivePointerId);
- final float x = MotionEventCompat.getX(ev, activePointerIndex);
- final int totalDelta = (int) (x - mInitialMotionX);
- int nextPage = determineTargetPage(currentPage, pageOffset, initialVelocity,
- totalDelta);
- setCurrentItemInternal(nextPage, true, true, initialVelocity);
-
- mActivePointerId = INVALID_POINTER;
- endDrag();
- needsInvalidate = mLeftEdge.onRelease() | mRightEdge.onRelease();
- }
- break;
- case MotionEvent.ACTION_CANCEL:
- if (mIsBeingDragged) {
- scrollToItem(mCurItem, true, 0, false);
- mActivePointerId = INVALID_POINTER;
- endDrag();
- needsInvalidate = mLeftEdge.onRelease() | mRightEdge.onRelease();
- }
- break;
- case MotionEventCompat.ACTION_POINTER_DOWN: {
- final int index = MotionEventCompat.getActionIndex(ev);
- final float x = MotionEventCompat.getX(ev, index);
- mLastMotionX = x;
- mActivePointerId = MotionEventCompat.getPointerId(ev, index);
- break;
- }
- case MotionEventCompat.ACTION_POINTER_UP:
- onSecondaryPointerUp(ev);
- mLastMotionX = MotionEventCompat.getX(ev,
- MotionEventCompat.findPointerIndex(ev, mActivePointerId));
- break;
- }
- if (needsInvalidate) {
- ViewCompat.postInvalidateOnAnimation(this);
- }
- return true;
- }
代碼C:void android.support.v4.view.ViewPager.onSecondaryPointerUp(MotionEvent ev)
- private void onSecondaryPointerUp(MotionEvent ev) {
- final int pointerIndex = MotionEventCompat.getActionIndex(ev);
- final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
- if (pointerId == mActivePointerId) {
-
-
- final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
- mLastMotionX = MotionEventCompat.getX(ev, newPointerIndex);
- mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
- if (mVelocityTracker != null) {
- mVelocityTracker.clear();
- }
- }
- }
總結
在這裏就不想上篇文章那樣分各類狀況去討論了。那樣有些無聊。這裏就重要點的說明一下個人理解,最後附一個我寫的demo供你們參考學習。spa
一、viewpager處理touch的思路:不截斷touch。假設touch移動知足了必定的條件,再截斷touch由該viewgroup處理。.net
二、咱們可以看到onInterceptTouchEvent和onTouchEvent方法裏的方法很是類似。對於一個touch事件。這兩個方法基本不會被都運行。僅僅有很是少的狀況下這兩個方法都會被運行。orm
三、viewpager有趣的現象。操做:單點操做viewpager。使viewpager響應事件,再加一個點觸碰viewpager。如此不斷加點,可以看到viewpager響應後加上去點的事件,這是爲何呢?代碼B第108--111行已經告訴咱們了,再也不解釋。blog
四、viewpager有趣的現象。操做:對於前面不不斷加上去的觸點,假設現在一共同擁有4個觸點。現在響應第4個觸點的事件,假設第4個觸點擡起,那麼viewpager響應哪一個觸點的事件呢?答案是第一個。
規律是什麼呢?擡起的觸點不是當前響應的。那麼沒影響;假設是當前響應的:假設擡起的觸點的pointerIndex不是0,那麼由pointerIndex最小的觸點來響應,因此由第一個來響應。代碼C已經很是明顯告訴咱們了。
假設這裏你看不懂,那麼你要學習一下android是怎麼處理多觸點事件的就會明確了。
Demo
下載地址:http://download.csdn.net/detail/u011647962/8507523