Cases triggered by the Android Touch event Transfer Mechanism

Source: Internet
Author: User
Tags gety xdiff

Cases triggered by the Android Touch event Transfer Mechanism

 

I have also written two articles about the Android Touch event transfer mechanism. I think the Touche event is still well understood, but I have encountered a problem recently, let me learn about the Android Touche event again.

My article on Android Touche event transfer mechanism is as follows:

Http://blog.csdn.net/yuanzeyao/article/details/37961997

Http://blog.csdn.net/yuanzeyao/article/details/38025165

 

I have come to the following conclusions in these two articles:

1. If a view is clickable, The onTouchEvent of this View will certainly return true, that is, any touch event will be consumed.

2. If a View is not consumed for the ACTION_DOWN event (onTouchEvent returns false), the subsequent ACTION_MOVE and ACTION_UP events will not be accepted, that is, there is no chance to process these events, these events are handled in the parent View.

3. If a ViewGroup wants to intercept an event (not to pass the event to the subview), it only needs to rewrite the onInterceptTouchEvent (MotionEvent ev) method of the ViewGroup so that it returns true, or call requestDisallowInterceptTouchEvent (true );

4. The Touche event in Android is the Activity passed from the underlying layer to the upstream layer-> DecorView-> ViewGroup-> View

 

After understanding the problem above, let's start to look at the problem I encountered,

When using SlideMenu, place only one TextView in the Activity, and you will find that SlideMenu cannot be moved. At that time, slide can be made through the Title on the top, because it is not very familiar with SlideMenu, at that time, I thought that the SlideMenu attribute was used incorrectly and the problem was not solved until a netizen said that setting the TextView clickable to true could solve the problem. I tried it, really good! Haha... do you understand the reasons? If you do not understand it, continue to read it.

 

According to my previous understanding of Touche events, if clickable is set, the Touche event will be consumed by TextView. If TextView is consumed, how can slide the SlideMenu? To solve this problem, do you still need to check the SlideMenu source code?

 

First, let's look at the methods related to mmviewabove and Touche in SlideMenu.

 

@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {if (!mEnabled)return false;final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;if (action == MotionEvent.ACTION_DOWN && DEBUG)Log.v(TAG, Received ACTION_DOWN);if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP|| (action != MotionEvent.ACTION_DOWN && mIsUnableToDrag)) {endDrag();return false;}switch (action) {case MotionEvent.ACTION_MOVE:try{final int activePointerId = mActivePointerId;if (activePointerId == INVALID_POINTER)break;final int pointerIndex = this.getPointerIndex(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 - mLastMotionY);if (DEBUG) Log.v(TAG, onInterceptTouch moved to:( + x + ,  + y + ), diff:( + xDiff + ,  + yDiff + ), mLastMotionX: + mLastMotionX);if (xDiff > mTouchSlop && xDiff > yDiff && thisSlideAllowed(dx)) {if (DEBUG) Log.v(TAG, Starting drag! from onInterceptTouch);startDrag();mLastMotionX = x;setScrollingCacheEnabled(true);} else if (yDiff > mTouchSlop) {mIsUnableToDrag = true;}}catch(IllegalArgumentException e){e.printStackTrace();}break;case MotionEvent.ACTION_DOWN:mActivePointerId = ev.getAction() & ((Build.VERSION.SDK_INT >= 8) ? MotionEvent.ACTION_POINTER_INDEX_MASK : MotionEvent.ACTION_POINTER_INDEX_MASK);mLastMotionX = mInitialMotionX = MotionEventCompat.getX(ev, mActivePointerId);mLastMotionY = MotionEventCompat.getY(ev, mActivePointerId);if (thisTouchAllowed(ev)) {mIsBeingDragged = false;mIsUnableToDrag = false;if (isMenuOpen() && mViewBehind.menuTouchInQuickReturn(mContent, mCurItem, ev.getX() + mScrollX)) {mQuickReturn = true;}} else {mIsUnableToDrag = true;}break;case MotionEventCompat.ACTION_POINTER_UP:onSecondaryPointerUp(ev);break;}if (!mIsBeingDragged) {if (mVelocityTracker == null) {mVelocityTracker = VelocityTracker.obtain();}mVelocityTracker.addMovement(ev);}return mIsBeingDragged || mQuickReturn;}

Look at this method. The logic in this method is that when sliding to a certain distance, true will be returned, that is, the sliding event will be intercepted, and the first ACTION_DOWN will certainly not be intercepted.

 

Let's take a look at onToucheEvent. java

 

@Overridepublic boolean onTouchEvent(MotionEvent ev) {if (!mEnabled)return false;//if (!mIsBeingDragged && !thisTouchAllowed(ev))//return false;if (!mIsBeingDragged && !mQuickReturn)return false;final int action = ev.getAction();if (mVelocityTracker == null) {mVelocityTracker = VelocityTracker.obtain();}mVelocityTracker.addMovement(ev);switch (action & MotionEventCompat.ACTION_MASK) {case MotionEvent.ACTION_DOWN:/* * If being flinged and user touches, stop the fling. isFinished * will be false if being flinged. */completeScroll();// Remember where the motion event startedmLastMotionX = mInitialMotionX = ev.getX();mActivePointerId = MotionEventCompat.getPointerId(ev, 0);break;case MotionEvent.ACTION_MOVE:if (!mIsBeingDragged) {if (mActivePointerId == INVALID_POINTER)break;final int pointerIndex = getPointerIndex(ev, mActivePointerId);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 - mLastMotionY);if (DEBUG) Log.v(TAG, onTouch moved to:( + x + ,  + y + ), diff:( + xDiff + ,  + yDiff + )mIsBeingDragged: + mIsBeingDragged + , mLastMotionX: + mLastMotionX);if ((xDiff > mTouchSlop || (mQuickReturn && xDiff > mTouchSlop / 4))&& xDiff > yDiff && thisSlideAllowed(dx)) {if (DEBUG) Log.v(TAG, Starting drag! from onTouch);startDrag();mLastMotionX = x;setScrollingCacheEnabled(true);} else {if (DEBUG) Log.v(TAG, onTouch returning false);return false;}}if (mIsBeingDragged) {// Scroll to follow the motion eventfinal int activePointerIndex = getPointerIndex(ev, mActivePointerId);if (mActivePointerId == INVALID_POINTER) {break;}final float x = MotionEventCompat.getX(ev, activePointerIndex);final float deltaX = mLastMotionX - x;mLastMotionX = x;float oldScrollX = getScrollX();float scrollX = oldScrollX + deltaX;final float leftBound = getLeftBound();final float rightBound = getRightBound();if (scrollX < leftBound) {scrollX = leftBound;} else if (scrollX > rightBound) {scrollX = rightBound;}// Don't lose the rounded componentmLastMotionX += scrollX - (int) scrollX;scrollTo((int) scrollX, getScrollY());pageScrolled((int) scrollX);}break;case MotionEvent.ACTION_UP:if (mIsBeingDragged) {final VelocityTracker velocityTracker = mVelocityTracker;velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);int initialVelocity = (int) VelocityTrackerCompat.getXVelocity(velocityTracker, mActivePointerId);final int scrollX = getScrollX();//final int widthWithMargin = getWidth();//final float pageOffset = (float) (scrollX % widthWithMargin) / widthWithMargin;// TODO test this. should get better flinging behaviorfinal float pageOffset = (float) (scrollX - getDestScrollX(mCurItem)) / getBehindWidth();final int activePointerIndex = getPointerIndex(ev, mActivePointerId);if (mActivePointerId != INVALID_POINTER) {final float x = MotionEventCompat.getX(ev, activePointerIndex);final int totalDelta = (int) (x - mInitialMotionX);int nextPage = determineTargetPage(pageOffset, initialVelocity, totalDelta);setCurrentItemInternal(nextPage, true, true, initialVelocity);} else {setCurrentItemInternal(mCurItem, true, true, initialVelocity);}mActivePointerId = INVALID_POINTER;endDrag();} else if (mQuickReturn && mViewBehind.menuTouchInQuickReturn(mContent, mCurItem, ev.getX() + mScrollX)) {// close the menusetCurrentItem(1);endDrag();}break;case MotionEvent.ACTION_CANCEL:if (mIsBeingDragged) {setCurrentItemInternal(mCurItem, true, true);mActivePointerId = INVALID_POINTER;endDrag();}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);int pointerIndex = this.getPointerIndex(ev, mActivePointerId);if (mActivePointerId == INVALID_POINTER)break;mLastMotionX = MotionEventCompat.getX(ev, pointerIndex);break;}return true;}

We focus on the ACTION_DWON event. For ACTION_DWON events, SlideMenu is not intercepted, so it is passed to TextView. Because TextView does not have clickable by default, it will not consume this event, if TextView is not consumed, the event is passed to SlideMenu, but we find that this event is not consumed in SlideMenu. Do you still remember conclusion 2 above? According to conclusion 2, we know that the subsequent events cannot be passed, so SlideMenu cannot be moved.

 

 

If clickable is set, the first ACTION_DOWN is processed by TextView. Therefore, each subsequent event is passed to TextView (provided that the event is not blocked, but the actual result is intercepted, it is processed by SlideMenu, so SlideMenu slides)

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.