- (一)Android事件分发机制 - View篇
- (二)Android事件分发机制 - ViewGroup篇
- (三)Android事件分发机制 - Activity篇
- (四)Android事件分发机制 - 总结篇
Android事件分发中三个重要方法:
public boolean dispatchTouchEvent(MotionEvent event)
dispatchTouchEvent
用来进行事件的分发。如果事件能够传递给当前的View
,那么此方法一定会被调用,返回结果表示是否分发当前事件。
public boolean onInterceptTouchEvent(MotionEvent ev)
onInterceptTouchEvent
是ViewGroup
提供的方法,返回结果表示是否拦截当前事件(默认返回false
),如果当前View
拦截了某个事件,那么在同一个事件序列当中,此方法不会被再次调用,
public boolean onTouchEvent(MotionEvent event)
onTouchEvent
在dispatchTouchEvent
方法中被调用,用来处理点击事件,返回结果表示是否消耗当前事件(默认返回true
),如果不消耗,则在同一个事件序列中,当前View
无法再次接受到事件。
三个方法的分布情况:
阅读Android事件分发的源代码(6.0版本)
- 一个事件序列是指从手指触摸屏幕开始,到手指离开屏幕结束,这个过程中产生的一系列事件。同一个事件序列是以
ACTION_DOWN
事件开始,中间含有数量不定的ACTION_MOVE
事件,最终以ACTION_UP
事件结束; - 事件传递的顺序是:
Activity -> Window -> View
,即事件总是先传递给Activity
,然后在传递给Window
,最后在传递给View
,顶级View
接收到事件后,就会按照事件分发机制去分发事件; - 事件的传递过程是由外向内的,即事件总是由父元素分发给子元素;
- 正常情况下,一个事件序列只能被一个
View
拦截且消耗。一旦一个View
拦截了某次事件,那么同一个事件序列内的所有事件都会直接交给它处理,因此同一个事件序列中的事件不能分别由两个View
同时处理,但是通过特殊手段可以做到,比如一个View
将本该自己处理的事件通过onTouchEvent强行传递给其他View
处理; - 某个
View
一旦开始处理事件,如果它不消耗ACTION_DOWN
事件,那么同一事件序列的其他事情都不会再交给它来处理,并且事件将重新交给它的父容器去处理(调用父容器的onTouchEvent
方法); - 某个
View
一旦开始处理事件,如果它消耗ACTION_DOWN
事件,但是不消耗其他类型事件,那么这个点击事件会消失,父容器的onTouchEvent
方法不会被调用,当前view
依然可以收到后续的事件,但是这些事件最后都会传递给Activity
处理; - 点击事件分发是到达顶级
View
后(一般是ViewGroup
),会首先调用dispatchTouchEvent
方法,其中它的onInterceptTouchEvent
方法如果返回true
,则会对事件传递进行拦截,事件由ViewGroup
处理;如果onInterceptTouchEvent
方法返回false
,则代表不对事件进行拦截(默认返回false
),此时子View
中的dispatchTouchEvent
方法将被调用,到此,事件已经由顶级View
传递给了下一层的View
,接下来的过程是一个递归循环的过程,和顶级View
事件分发过程是一致的,直到完成整个事件分发。