(1)Activity:控制生命周期 & 处理事件bash
(2)ViewGroup:一组View的集合(含多个子View)ide
(3)View:全部UI组件的基类布局
(1)dispatchTouchEvent(MotionEvent ev): 用来进行事件分发;ui
(2)onInterceptTouchEvent(MotionEvent ev): 判断是否拦截事件(只存在于ViewGroup 中);this
(3)onTouchEvent(MotionEvent ev): 处理点击事件spa
从activity的dispatchEvent(MotionEvent ev)方法开始进行事件的分发,代码以下:3d
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()方法:code
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}复制代码
由以上代码能够发现PhoneWindow的superDispatchTouchEvent()方法里面调用的是mDecor.superDispatchTouchEvent()方法。mDecor就是窗口的顶层布局DecorView。DecorView中的super.DispatchTouchEvent()方法最终调用的是ViewGroup的的dispatchTouchEvent方法。cdn
以上是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消费,事件结束
}
复制代码
ViewGroup的事件分发dispatchTouchEvent()方法能够用一段伪代码来解释:
由上图咱们能够明白:ViewGroup的dispatchTouchEvent()方法中调用了onInterceptTouchEvent()方法来判断是否拦截事件,若是拦截,则调用本身的onTouchEvent()方法。若是不拦截,则调用子View的dispatchTouchEvent()方法,将事件分发给子View处理。
View的dispatchTouchEvent()事件分发的伪代码实现:
由吸上伪代码能够判断,当View设置了TouchListener的时候,会先调用TouchListener的onTouch()方法,若是onTouch()方法返回true,则不会执行View的onTouchEvent()方法,若是返回false才会执行onTouchEvent()方法。TouchListener、onTouchEvent、ClickListener的优先顺序是:TouchListener>onTouchEvent>ClickListener.
上图介绍了事件分发机制的总体流程:
首先事件分发以后由activity分发到达根布局ViewGroup,以后会调用ViewGroup的dispatchTouchEvent()方法,dispatchTouchEvent()方法中经过调用ViewGroup自身的interceptTouchEvent()方法来判断是否对时间进行拦截,若是拦截,则调用自身的onTouchEvent()方法,onTouchEvent()方法判断是否消费事件,若是消费则事件消费结束,若是不消费,则交给activity的onTouchEvent()方法进行处理;若是不拦截,则事件会交给子View处理,若是子View也是ViewGroup的话,流程跟以上同样;若是View没有子View的话,则会调用View的dispatchTouchEvent()方法,View中是没有拦截方法,全部会直接调用本身的onTouchEvent()方法处理事件,若是事件被消费则事件消费结束,若是View没有消费事件,则交给它的父ViewonTouchEvent()方法处理,若是父容器都不处理,最终会调用activity的onTouchEvent()方法。