这篇文章是针对 Carson_Ho 的文做的笔记和总结,原文地址:https://www.jianshu.com/p/38015afcdb58 。
几个基本要点:
1,分发的是什么?Touch事件。
2,分发的顺序:Activity -->ViewGroup -->View。
3,三个关键方法:dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent。
源码中,activity在dispatchTouchEvent 的时候,对于每次ACTION_DOWN都会调用onUserInteraction方法,这是个空方法,重写该方法可以实现一些特殊的功能。dispatchTouchEvent 的第一层拦截是getWindow()的superDispatchTouchEvent(查看PhoneWindow代码,发现它有一大堆superDispatch***Event),该方法调用了DecorView的superDispatchTouchEvent,也就是ViewGroup的dispatchTouchEvent(DecorView extends FrameLayout),若未处理,则调用activity的onTouchEvent。注意这里activity并无调用onInterceptTouchEvent(因为不需要)。所以在activity层,如果没有view处理点击事件,则activity的onTouchEvent可以触发,而如果有view处理了点击事件,则activity的onTouchEvent不会触发。
ViewGroup 版本变迁很大。但是大致的思路还是相同的。dispatchTouchEvent 的时候要判断是否要拦截该事件,若拦截则不会继续向下分发,而是由自己处理,这部分代码暂时无法读懂什么意思。若没有拦截,则会遍历child view,如果该view位于点击区域,则会调用 dispatchTransformedTouchEvent来判断该子view是否处理该事件,这里transform主要是对点击坐标的转换。
可见,一旦onInterceptTouchEvent返回true,则该事件由viewgroup自身处理,dispatchTouchEvent返回true,则事件不再向下分发。所以,自定义view的时候,如果想要自己处理onTouchEvent而不希望子view来处理,则可重写onInterceptTouchEvent 令其返回true,并重写onTouchEvent即可(若自定义的view继承自View而不是ViewGroup,则不用重写onInterceptTouchEvent)。