首先我们知道,一个点击事件产生后,它的事件传递顺序遵循:
Activity->Window ->View
1.Activity对点击事件的分发过程
点击事件用MotionEvent来表示,当一个点击事件发生后,首先会传递给当前的Activity,,由Activity的dispatchTouchEvent方法来进行事件派发,具体是由Actiivty内部的window来完成的。window会将事件传递给decorView,decorView一般为当前界面的底层容器,通过Activity.getWindow.getDecorView()可以获得.
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
由上面的代码可知,Activity的点击事件由当前activity的附属window进行分发,如果返回ture,则整个事件的循环结束了。如果返回false,则事件没有人处理,当所有View的onTouchEvent方法都返回false时,那么Activity的onTouchEvent方法会被调用。
2.window点击事件的分发过程
@Override
public boolean superDispatchKeyEvent(KeyEvent event) {
return mDecor.superDispatchKeyEvent(event);
}
PhoneWindow(Window是个抽象类,PhoneWindow是Window的实现类)将事件直接传递给了DecorView.DecorView是PhoneWindow中一个内部类,在PhoneWindow中有这样一句。
getWindow().getDecorView()返回的是一个DecorView。我们可以通过一个setContenView设置的View是DecorView的子view,由于DecorView是继承FramLayout而且是View的父元素,所以点击事件一定会传递给view,这个view就是顶级view,DecorView是根view。
3、顶级View对点击事件的分发过程
顶级view一般是ViewGroup,当点击事件传递到顶级的ViewGroup时,ViewGroup会调用自己的dispatchTouchEvent方法,一层层分发下去,最后传递给view的onTouchEvent方法。
具体传递顺序:对于一个根ViewGroup来讲,首先会调用dispatchTouchEvent,如果此时它的onInterceptTouchEvent方法返回ture,表示拦截当前的事件,说明本次事件交给当前的ViewGroup处理,调用它的onTouchEvent方法。如果返回false,表示不拦截此次事件,继续分发给它的子元素,接着它的子元素的dispatchTouchEvent接着会被调用,如此反复直到事件的结束。