大师网-带你快速走向大师之路 解决你在学习过程中的疑惑,带你快速进入大师之门。节省时间,提升效率

Android事件分发笔记

我们主要研究的几个方法:dispatchTouchEvent,onInterceptTouchEvent,onTouch, onTouchEvent,onClick。

  • dispatchTouchEvent
    该方法主要是用来进行事件分发和传递的,当返回true的时候代表自己去处理,把事件传递给自己,否则就传递给其他的view。该方法也是触摸事件第一个执行的方法,后续的几个是否执行都取决于它。
  • onInterceptTouchEvent
    这个方法主要是viewGroup特有的,用来做触摸事件拦截的,默认返回false。
    • 主要是用来做事件分发过程中的拦截的,相当于一个拦截器
    • 如果返回false或者super,则事件继续传递,事件所经过的每一层的viewGroup都会去调用该方法来询问是否拦截
    • 如果返回true,则代表拦截该事件,停止传递给子view,会走自己的onTouchEvent事件
    • 不像onTouchEvent是否拦截取决于down事件,该方法每个事件都可以去做拦截
    • 事件一经拦截,后续move、up事件都直接交给onTouchEvent,不会重新去询问是否拦截(即不再调用onInterceptTouchEvent)
    • 事件被拦截后,子view会接收到一个cancel事件,来恢复之前的状态,结束当前事件流
  • onTouch
    这个也是触摸事件,方便给开发者调用的。根据注释:当一个触摸事件被分发到一个view的时候,就会调用该方法,它是在事件传递到onTouchEvent之前被调用的。
  • onTouchEvent
    该方法就是真正用来处理触摸事件的最后调用的方法,在这里你可以自己写你的触摸事件算法。
  • onClick
    这个就是我们最熟悉的点击事件了,它也属于触摸事件的一个内容,有一点需要注意就是他是在onTouchEvent的UP事件里面执行的。
    执行顺序:onTouch—>onTouchEvent—>onClick
  • 事件流程图


    事件分发流程图.png
  • 说明
    • dispatchTouchEvent和onTouchEvent一旦返回true,事件就被消费掉了,该事件就消失了,不会往下传递也不会向上回溯
    • dispatchTouchEvent和onTouchEvent一旦返回false,事件就会回溯到父控件的onTouchEvent,说明自己不处理
    • dispatchTouchEvent返回false和true对于Activity来说都是一样,因为他是最顶层的事件接收者,而ViewGroup和View返回super则是向下传递,返回false就是向父控件的onTouchEvent回溯事件。
    • onTouchEvent返回super代表向上回溯事件,返回false则代表自己不处理,所以也是向上回溯事件,如果最终都没消费,则Activity消费,事件消失。
    • onInterceptTouchEvent默认返回super,通过源码我们知道其实就是返回false,默认是不去拦截事件的,这也符合常理,可以让子view有机会去捕获事件,返回true则代表拦截了这个事件,交给自己的onTouchEvent去处理,ViewGroup的dispatchTouchEvent的super默认实现就是调用自己的onInterceptTouchEvent,这也就可以保证事件有机会分发到自己的onTouchEvent
    • dispatchTouchEvent和onTouchEvent都是以Down事件为基准,来判断后续事件是否经过自己,也就是自己消费,如果Down事件返回了false或者super,则后续事件都不再经过自己了,包括move,up,如只有返回true的时候,后续事件才会经过自己
  • 实例
    • case 1 : 全部返回super


      图片.png
    • case 2:view的onTouchEvent 返回true


      图片.png
    • case 3:View的dispatchTouchEvent返回true


      图片.png
    • case 4:ViewGroup的onTouchEvent返回true


      图片.png
    • case 5:ViewGroup的onInterceptTouchEvent返回true,并且onTouchEvent也返回true


      图片.png

      可以看到被拦截之后,后续move,up事件都交给自己处理,并且不再调用onIntercepetTouchEvent,而且事件也不再传递到子View。

  • 关于ACTION_DOWN
    • 首先,对于dispatchTouchEvent和onTouchEvent,事件是否消费实在DOWN中决定的,如果DOWN中没有返回true,则后续的move,up都不会再来
    • 举例:view的onTouchEvent中DOWN事件返回true


      图片.png

      可以看到,相比view的onTouchEvent中返回true,多出了最后一行日志。这是因为只有down返回了true,仅仅是让后续事件经过自己,但是move、up事件返回的还是super,而ViewGroup的onTouchEvent事件已经被跳过,所以up事件回溯到Activity了。在move,up事件中返回true则起不到在down中返回true的效果。

    • 再举一例:我们在view的onTouchEvent中down事件返回false看一下:


      图片.png

      可以看到,down中返回false之后,后续move,up事件都不在经过自己了,所以说down事件起到了决定事件流向的作用。

    • 为了解释清楚,我们再把view的dispatchTouchEvent的DOWN返回true看一下:


      图片.png

      可以看到,事件走到View的dispatchTouchEvent后就停止了,因为这里返回了true,代表事件在这里消费了,而后续的UP事件同样也是走到view的dispatchTouchEvent,由于up返回的是super,所以走了自身的onTouchEvent的up,然后这里返回的也是super,所以又回溯给Activity的onTouchEvent的up了。

    • 对应的view的dispatchTouchEvent的DOWN返回false
      图片.png

      前面提到过,对于dispatchTouchEvent和onTouchEvent,事件是否消费实在DOWN中决定的,如果DOWN中没有返回true,则后续的move,up都不会再来