关于Android中的事件机制,用到的地方仍是不少的,而且这个知识点还真有点复杂。测试
在写这篇文章前,网上看了很多博文,有的写的感受挺不错的。只是当时感受好像理解了,过后又很容易忘。如今本身也系统整理下吧。
spa
Android中的事件在表现形式上有不少,如onTach、onClick和onLongClick等,在具体微观上的表现形势有action_down、action_move和action_up等。blog
不管哪一种事件表现类型,首先都是基于事件的传递模型。其实Android中的事件传递有点相似于JS中事件传递模型。都是基于先捕获而后冒泡的形式。事件
在捕获阶段,事件先由外部的View接收,而后传递给其内层的View,依次传递到更够接收此事件的最小View单元,完成事件捕获过程;get
在冒泡阶段,事件则从事件源的最小View单元开始,依次向外冒泡,将事件对层传递。it
事件的捕获和冒泡是整个事件的传递流程,可是在实际的传递过程当中,Android中则表现的相对复杂。io
主要表如今能够控制每层事件是否继续传递(由事件分发和事件拦截协同进行),以及事件的具体消费(由事件消响应进行,但须要注意的是,事件分发自身也具备事件消费能力)。file
也就是本文说起的事件分发、拦截和响应。方法
Android中不一样的控件所具备的事件分发、拦截和响应稍有不一样,主要表如今Activity自己不具备事件拦截,不是ViewGroup的最小view单元不具备事件分发和事件拦截(由于它没有本身的子View)。im
具体对应关系以下图所示:
对于控制Android中的事件传递和消费机制,最主要须要注意的就是这几个方法的返回值了。
事件分发:public boolean dispatchTouchEvent(MotionEvent ev)
当有监听到事件时,首先由Activity的捕获到,进入事件分发处理流程。不管是Activity仍是View,如前文所说,事件分发自身也具备消费能力,
若是事件分发返回true,表示改事件在本层再也不进行分发且已经在事件分发自身中被消费了。至此,事件已经完结。若是你不想Activity中的任何控件具备任何的事件消费能力,
最简答的方法能够重写此Activity的dispatchTouchEvent方法,直接返回true就ok。
若是事件分发返回 false,代表事件在本层再也不继续进行分发,并交由上层控件的onTouchEvent方法进行消费。
固然了,若是本层控件已是Activity,那么事件将被系统消费或处理。
若是事件分发返回系统默认的 super.dispatchTouchEvent(ev),事件将分发给本层的事件拦截onInterceptTouchEvent 方法进行处理
(若是本层控件是Activity,因为其没有事件拦截,所以将直接将事件传递到子View,并交给子View的事件分发进行处理)。
事件拦截:public boolean onInterceptTouchEvent(MotionEvent ev)
若是 onInterceptTouchEvent 返回 true,则表示将事件进行拦截,并将拦截到的事件交由本层控件 的 onTouchEvent 进行处理;
若是返回结果是false;则表示不对事件进行拦截,事件得以成功分发到子View。并由子View的dispatchTouchEvent进行处理。
若是返回super.onInterceptTouchEvent(ev),事件默认不会被拦截,交由子View的dispatchTouchEvent进行处理。
事件响应:public boolean onTouchEvent(MotionEvent ev)
若是onTouchEvent返回true,表示onTouchEvent处理完事件后消费了这次事件。此时事件终结,将不会进行后续的冒泡。
若是onTouchEvent返回false,事件在onTouchEvent中处理后继续向上层View冒泡,且有上层View的onTouchEvent进行处理。
若是返回super.onTouchEvent(ev),则默认处理的逻辑和返回false时相同。
总结:从以上过程当中能够看出,dispatchTouchEvent不管返回true仍是false,事件都再也不进行分发,
只有当其返回super.dispatchTouchEvent(ev),才代表其具备向下层分发的愿望,
可是是否可以分发成功,则须要通过事件拦截onInterceptTouchEvent的审核。事件是否具备冒泡特是由onTouchEvent的返回值决定的。
测试用例: