android MotionEvent.ACTION_CANCEL情景分析

今天在温习ViewGroup的dispatchTouchEvent理解这篇文章的时候,偶然间发现了MotionEvent.ACTION_CANCEL使用的情景,温故而知新,说的就是这了。
还是直入主题吧。
情景:ScrollView中有一个Button。手指触下Button区域进行滑动的过程中,Button会收到ScrollView传给Button的MotionEvent.ACTION_CANCEL事件。

具体分析

声明:文中所述的代码行数对应android5.1(api22)的源码行数。

  1. 手指触下Button区域时,对应ACTION_DOWN。
    ScrollView的dispatchTouchEvent()(即是ViewGroup的dispatchTouchEvent)收到event,执行ViewGroup的1960行,调用了ScrollView的onInterceptTouchEvent()方法,ScrollView的535–》582,ScrollView的onInterceptTouchEvent()返回false。ViewGroup执行1985–》1995–》2049,由于2049行中的dispatchTransformedTouchEvent()方法返回true(因为Button是可点击的,也就是clickable是true,Button的onTouchEvent必会返回true),执行2065行,mFirstTouchTarget被赋值,mFirstTouchTarget.child为该Button,2102–》2141。

  2. 滑动过程中,对应ACTION_MOVE。
    由于mFirstTouchTarget不为空,ViewGroup中执行1960,调用了ScrollView的onInterceptTouchEvent()方法,ScrollView的515,如果滑动量小于mTouchSlop,则onInterceptTouchEvent还是返回的false,当滑动量大于mTouchSlop时,onInterceptTouchEvent返回true。ViewGroup中不会进1985的if判断,执行2104行,cancelChild为true,执行2106–》2371–》2375,这里就传给Button一个ACTION_CANCEL的Event。

其实ViewGroup的dispatchTouchEvent理解中的结论三就是这种情景,都是父视图的onInterceptTouchEvent先返回false,子控件消费事件(dispatchTouchEvent返回true),然后在某种情况下onInterceptTouchEvent返回true,子控件就会收到ACTION_CANCEL的Event。

其应用场景的思考

对于View而言,在View的onTouchEvent中对ACTION_CANCEL的处理:

case MotionEvent.ACTION_CANCEL:
       setPressed(false);
       removeTapCallback();
       removeLongPressCallback();
       break;

SeekBar的onTouchEvent对ACTION_CANCEL的处理:

case MotionEvent.ACTION_CANCEL:
       if (mIsDragging) {
           onStopTrackingTouch();
           setPressed(false);
       }
       invalidate(); // see above explanation
       break;

ViewPager的onTouchEvent对ACTION_CANCEL的处理:

case MotionEvent.ACTION_CANCEL:
       if (mIsBeingDragged) {
           scrollToItem(mCurItem, true, 0, false);
           mActivePointerId = INVALID_POINTER;
           endDrag();
           needsInvalidate = mLeftEdge.onRelease() | mRightEdge.onRelease();
       }
       break;

拿ViewPager来说,在ScrollView包含ViewPager的情况下,对ViewPager做左右滑动,滑到一页的一半时往上下滑,ViewPager收到MotionEvent.ACTION_CANCEL后就能够回到先前那一页,而不是停在中间。

关于MotionEvent的参考资料:安卓自定义View进阶-MotionEvent详解

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值