1.事件的定义:
2.事件序列
3.事件分发的对象
(1)Activity:控制生命周期 & 处理事件
(2)ViewGroup:一组View的集合(含多个子View)
(3)View:所有UI组件的基类
4.事件分发的主要方法
(1)dispatchTouchEvent(MotionEvent ev): 用来进行事件分发;
(2)onInterceptTouchEvent(MotionEvent ev): 判断是否拦截事件(只存在于ViewGroup 中);
(3)onTouchEvent(MotionEvent ev): 处理点击事件
5.Activity的事件分发:
从activity的dispatchEvent(MotionEvent ev)方法开始进行事件的分发,代码如下:
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction(); //空方法,子类可重写
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}我们可以看到activity的dispatchTouchEvent(MotionEvent ev) 方法中调用了getWindow().superDispatchTouchEvent()方法。getWindow()就是window的唯一实现类PhoneWindow。所有我们可以接着看PhoneWindow中的superDispatchTouchEvent()方法:
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}由以上代码可以发现PhoneWindow的superDispatchTouchEvent()方法里面调用的是mDecor.superDispatchTouchEvent()方法。mDecor就是窗口的顶层布局DecorView。DecorView中的super.DispatchTouchEvent()方法最终调用的是ViewGroup的的dispatchTouchEvent方法。
以上是activity到ViewGroup的时间分发流程,再来看看activity的dispatchTouchEvent()方法,如果getWindow().superDispatchTouchEvent()方法返回true,表示事件被activity中的子控件消费,如果返回false,则会执行activity的onTouchEvent()方法。我们来看看activity的onTouchEvent()方法:
public boolean onTouchEvent(MotionEvent event) {
if (mWindow.shouldCloseOnTouch(this, event)) { //判断是否有超出边界,如果超出,直接finish
finish();
return true;
}
return false; //如果没有超出,表示事件没有被activity消费,事件结束
}
6.ViewGroup的时间分发
ViewGroup的事件分发dispatchTouchEvent()方法可以用一段伪代码来解释:
由上图我们可以明白:ViewGroup的dispatchTouchEvent()方法中调用了onInterceptTouchEvent()方法来判断是否拦截事件,如果拦截,则调用自己的onTouchEvent()方法。如果不拦截,则调用子View的dispatchTouchEvent()方法,将事件分发给子View处理。
7.View的事件分发
View的dispatchTouchEvent()事件分发的伪代码实现:
由吸上伪代码可以判断,当View设置了TouchListener的时候,会先调用TouchListener的onTouch()方法,如果onTouch()方法返回true,则不会执行View的onTouchEvent()方法,如果返回false才会执行onTouchEvent()方法。TouchListener、onTouchEvent、ClickListener的优先顺序是:TouchListener>onTouchEvent>ClickListener.
8.事件分发机制总结
上图介绍了事件分发机制的整体流程:
首先事件分发之后由activity分发到达根布局ViewGroup,之后会调用ViewGroup的dispatchTouchEvent()方法,dispatchTouchEvent()方法中通过调用ViewGroup自身的interceptTouchEvent()方法来判断是否对时间进行拦截,如果拦截,则调用自身的onTouchEvent()方法,onTouchEvent()方法判断是否消费事件,如果消费则事件消费结束,如果不消费,则交给activity的onTouchEvent()方法进行处理;如果不拦截,则事件会交给子View处理,如果子View也是ViewGroup的话,流程跟以上一样;如果View没有子View的话,则会调用View的dispatchTouchEvent()方法,View中是没有拦截方法,所有会直接调用自己的onTouchEvent()方法处理事件,如果事件被消费则事件消费结束,如果View没有消费事件,则交给它的父ViewonTouchEvent()方法处理,如果父容器都不处理,最终会调用activity的onTouchEvent()方法。