虽然网上有很多讲解的很详细的安卓事件传递的文章,但是都只是讲解的理论知识很少有具体到代码的走向以及activity和view之间的事件传递.
本文通过断点粗略的讲解没有任何拦截情况下的事件传递以及方法的走向和activity和view之间的事件传递
接下来将根据这张简单的布局图来进行断点讲解
首先来探讨activity和view之间的事件传递
先来张断点图
可以很明显的看出,最先收到触摸事件的对象为DecorView,是不是和网上的一些文章写的不太一样
查阅源码我们看到,DecorView重写了dispatchTouchEvent方法
通过一系列的中转,最终传递给了activity的dispatchTouchEvent
所以:触摸事件的传递应该是DecorView通过重写dispatchTouchEvent传递给Activity的dispatchTouchEvent方法,那activity又是怎么传递给view的呢?
接下来我们再看看activity的dispatchTouchEvent方法
getWindow()返回的是 PhoneWindow
通过PhoneWindow又传递给了DecorView.superDispatchTouchEvent(event);
有意思的是DecorView又调用了 super.dispatchTouchEvent(event);
即,事件又传递到了ViewGroup(DecorView)的dispatchTouchEvent
接下来就进入了正常的view间的事件传递
所以,说事件是从activity传递到DecorView好像也没有毛病
总结:activity与view之间的事件传递为 DecorView通过重写dispatchTouchEvent传递给activity的dispatchTouchEvent,然后activity在dispatchTouchEvent方法中又传递给DecorView的父类ViewGroup的dispatchTouchEvent,最后整个view之间的事件传递走上了正轨.
再补充一点:
可以看出当所有的view都不消费事件时,事件就会传递到activity的onTouchEvent方法
然后讲ViewGroup对触摸事件的处理
在ViewGroup的dispatchTouchEvent方法中,首先调用了onInterceptTouchEvent
当ViewGroup不拦截触摸事件时,ViewGroup会遍历子view,然后通过dispatchTransformedTouchEvent调用子view的dispatchTouchEvent方法,最终进入View内部的事件传递
当没有子View消费事件时,ViewGroup会调用super.dispatchTouchEvent(event);即父类的dispatchTouchEvent方法,把ViewGroup当作View来处理
总结:ViewGroup会先通过onInterceptTouchEvent来控制自己是否消费事件,当自己不消费时会遍历自己的子view是否消费事件,当自己的子view不消费时会调用自己父类的onInterceptTouchEvent方法把自己当个View处理
其中,当事件被消费时会给一些变量赋值,来控制以后所有的move等事件就会在被拦截处中断,不再进行向下级询问
最后讲View对触摸事件的处理
view对事件的处理就很简单了
基本上先判断了mOnTouchListener方法,然后就直接调用了onTouchEvent方法