android中的事件分发,可以说是面试经常被提及,日常开发中也偶尔会遇到一些事件冲突,弄清楚整个事件分发的流程,是一个基本功,作为搬砖的码农,基础还是要打牢固。

  其实网上关于事件分发的文章已经很多了,但是自己总结一下,印象总会深刻一点。
推荐一篇觉得介绍很详细的博文:安卓自定义View进阶-事件分发机制原理


  先介绍一下事件分发相关方法,X表示不含有该方法:

Touch事件相关方法

方法功能

ViewGroup

View

Activity

boolean dispatchTouchEvent (MotionEvent ev)

事件分发




boolean onInterceptTouchEvent (MotionEvent ev)

事件拦截


X

X

boolean onTouchEvent (MotionEvent ev)

事件响应




  首先来一张图:

android 模拟事件发送 android事件分发图解_ Android事件分发

  如果觉得图看完后,还是觉得有点不理解,再看下面的文字总结

1. dispatchTouchEvent
   dispatchTouchEvent处理事件分发,且事件分发本身也具有消费能力。

dispatchTouchEvent返回值

含义

true

表示该事件再本层不再进行分发,且事件已经在分发自身中被消费来,至此,该事件已经完结

false

表示该事件在本层不再继续进行分发,并交由上层控件的onTouchEvent方法去消费(其实是先交给来上层控件的dispatchTouchEvent方法,然后dispatchTouchEvent再调用了自身的onTouchEvent)

super.dispatchTouchEvent(ev)

事件将会分发给本层的事件拦截onInterceptTouchEvent方法进行处理

2. onInterceptTouchEvent
  onInterceptTouchEvent处理事件拦截

onInterceptTouchEvent返回值

含义

true

表示将事件拦截,并交由本层的控件的onTouchEvent处理

false

表示不拦截,事件将分发到子View,并交由子View的dispatchTouchEvent方法进行处理

super.onInterceptTouchEvent(ev)

事件默认不会被拦截,并交由子View的dispatchTouchEvent方法进行处理

3. onTouchEvent
  onTouchEvent处理事件消费

onTouchEvent返回值

含义

true

表示消费了此事件,此时事件终结,将不会继续将事件向上层回传

false

表示未消费事件,将事件继续向上层控件回传,且由上层View的onTouchEvent处理

super.onTouchEvent(ev)

效果同false,表示未消费事件,将事件继续向上层控件回传,且由上层View的onTouchEvent处理

  注意点1:dispatchTouchEvent的记忆功能
若子View的onTouchEvent放回false,则表示没有消费该事件,交由上层ViewGroup的onTouchEvent处理,然后改次的后续事件 MOVE 、UP 都直接交由上层ViewGroup的onTouchEvent处理。可以理解成下层员工第一件事件就说搞不定,需要上层领导来处理,那么上层领导后续就不会把该次的其他后续事件交给员工了,直接自己处理。

如下表所示,从上到下依次进行,假设事件都能正常向下传递

控件

事件分发相关方法

当前的事件名称

ViewGroup

dispatchTouchEvent

ACTION_DOWN

ViewGroup

onInterceptTouchEvent

ACTION_DOWN

View

dispatchTouchEvent

ACTION_DOWN

View

onTouchEvent (返回了false)

ACTION_DOWN

ViewGroup

onTouchEvent

ACTION_DOWN

ViewGroup

dispatchTouchEvent

ACTION_MOVE

ViewGroup

onTouchEvent

ACTION_MOVE

ViewGroup

dispatchTouchEvent

ACTION_UP

ViewGroup

onTouchEvent

ACTION_UP

  注意点2:当子View的onTouchEvent返回true时,事件被消费,上层ViewGroup的onTouchEvent不会执行。可以理解成,当下层员工把事件都搞定了,上层leader就不用再去处理该事件了,继续分发下一个事件给员工

  注意点3:当ViewGroup的onTouchEvent返回true时,且自身的onInterceptTouchEvent也返回true,则后续的事件ACTION_MOVE、ACTION_UP都不再继续向下层分发,直接交由本层的onTouchEvent处理。可以理解成上级leader在分发任务给下级时,下级没有搞定,然后发现自己能搞定,那么后续的事情就都自己搞定了

如下表所示,从上到下依次进行,

控件

事件分发相关方法

当前的事件名称

ViewGroup

dispatchTouchEvent

ACTION_DOWN

ViewGroup

onInterceptTouchEvent(返回了true)

ACTION_DOWN

ViewGroup

onTouchEvent (返回了true)

ACTION_DOWN

ViewGroup

dispatchTouchEvent

ACTION_MOVE

ViewGroup

onTouchEvent

ACTION_MOVE

ViewGroup

dispatchTouchEvent

ACTION_UP

ViewGroup

onTouchEvent

ACTION_UP

  还由一个相关的方法叫requestDisallowInterceptTouchEvent(true), 是告诉父View,不要拦截该事件,父View不再调用onInterceptTouchEvent,直接将事件传递到子View, requestDisallowInterceptTouchEvent(false)是告诉父View可以对事件进行拦截,具体内容可以自行百度。

  后续有时间了,会再写一篇有关滑动事件冲突解决的文章。