Android 事件分发,你真的了解吗?

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

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


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

Touch事件相关方法 方法功能 ViewGroup View Activity
boolean dispatchTouchEvent (MotionEvent ev) 事件分发
boolean onInterceptTouchEvent (MotionEvent ev) 事件拦截 X X
boolean onTouchEvent (MotionEvent ev) 事件响应

  首先来一张图:
这里写图片描述

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

  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可以对事件进行拦截,具体内容可以自行百度。

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

猜你喜欢

转载自blog.csdn.net/unicorn97/article/details/80836500