再探安卓触摸事件传递

虽然网上有很多讲解的很详细的安卓事件传递的文章,但是都只是讲解的理论知识很少有具体到代码的走向以及activity和view之间的事件传递.

本文通过断点粗略的讲解没有任何拦截情况下的事件传递以及方法的走向和activity和view之间的事件传递

接下来将根据这张简单的布局图来进行断点讲解


image.png

首先来探讨activity和view之间的事件传递

先来张断点图

image.png

可以很明显的看出,最先收到触摸事件的对象为DecorView,是不是和网上的一些文章写的不太一样

查阅源码我们看到,DecorView重写了dispatchTouchEvent方法


image.png
image.png

通过一系列的中转,最终传递给了activity的dispatchTouchEvent

所以:触摸事件的传递应该是DecorView通过重写dispatchTouchEvent传递给Activity的dispatchTouchEvent方法,那activity又是怎么传递给view的呢?

接下来我们再看看activity的dispatchTouchEvent方法

image.png

getWindow()返回的是 PhoneWindow
通过PhoneWindow又传递给了DecorView.superDispatchTouchEvent(event);


image.png

有意思的是DecorView又调用了 super.dispatchTouchEvent(event);
即,事件又传递到了ViewGroup(DecorView)的dispatchTouchEvent
接下来就进入了正常的view间的事件传递

image.png

所以,说事件是从activity传递到DecorView好像也没有毛病

总结:activity与view之间的事件传递为 DecorView通过重写dispatchTouchEvent传递给activity的dispatchTouchEvent,然后activity在dispatchTouchEvent方法中又传递给DecorView的父类ViewGroup的dispatchTouchEvent,最后整个view之间的事件传递走上了正轨.

再补充一点:

image.png

可以看出当所有的view都不消费事件时,事件就会传递到activity的onTouchEvent方法

然后讲ViewGroup对触摸事件的处理

在ViewGroup的dispatchTouchEvent方法中,首先调用了onInterceptTouchEvent


image.png

当ViewGroup不拦截触摸事件时,ViewGroup会遍历子view,然后通过dispatchTransformedTouchEvent调用子view的dispatchTouchEvent方法,最终进入View内部的事件传递


image.png
image.png

当没有子View消费事件时,ViewGroup会调用super.dispatchTouchEvent(event);即父类的dispatchTouchEvent方法,把ViewGroup当作View来处理

image.png
image.png

总结:ViewGroup会先通过onInterceptTouchEvent来控制自己是否消费事件,当自己不消费时会遍历自己的子view是否消费事件,当自己的子view不消费时会调用自己父类的onInterceptTouchEvent方法把自己当个View处理

其中,当事件被消费时会给一些变量赋值,来控制以后所有的move等事件就会在被拦截处中断,不再进行向下级询问

最后讲View对触摸事件的处理

view对事件的处理就很简单了

image.png

基本上先判断了mOnTouchListener方法,然后就直接调用了onTouchEvent方法

总结:一张大致的事件传递图来说明问题

image.png

你可能感兴趣的:(再探安卓触摸事件传递)