分native侧事件派发到java侧和Framework派发事件到UI,流程看源码即可,此处不赘叙,
Native侧派发事件的干活类图如下:
Framework侧派发事件的类图如下:
从Activity.dispatchTouchEvent开始,Action_Down事件派发的时序如下:
分析Android 5.0源码可知,ViewGroup的事件派发是一个后序遍历树的递归过程,在Action_Down事件的处理中做了两个事情:
1.递归查找touchTarget,并标记在ViewGroup的mFirstTouchTarget,整个流程下来,会生成一个touchTarget的链表,
示例如下:
若CustomView在onTouchEvent返回true,则生成的touchTarget链表为
DecorView->Content->…->RelativeLayout->CustomViewGroup->CustomView
具体实现逻辑在ViewGroup.dispatchTouchEvent和addTouchTarget中:
生成touchTarget链表后,在处理后面的Action_Up事件时,只需按照该touchTarget便可以快速找到
目标view,触发其onTouch/onTouchEvent/onClick,其他ViewGroup/View的onTouch/onTouchEvent便skip了。
2.按照Activity.dispatchTouchEvent->ViewGroup.dispatchTouchEvent->View.dispatchTouchEvent->View.onTouch/onTouchEvent->ViewGroup.onTouch/onTouchEvent->Activity.onTouchEvent派发时序调用
api,若派发中间事件被消耗(return true),则后续事件处理则skip。
下面分析下Action_Up事件的处理流程,ViewGroup.dispatchTouchEvent会检查mFirstTouchTarget,若mFirstTouchTarget==null,则表明该ViewGroup的子节点均不在Action_Down事件处理生成的target链表上,执行其View.dispatchTouchEvent,若从DecorView开始的整颗树均不在target链表上,则最后由Activity.onTouch执行,
对应的代码如下:
ViewGroup.dispatchTouchEvent
ViewGroup.dispatchTransformedTouchEvent
若mFirstTouchTarget不为null,则依照target链表不断调用dispatchTouchEvent,找到最终的目标View,执行其onTouch/onTouchEvent,其逻辑如下:
在onTouch和onTouchEvent执行中,默认的处理返回false,即点击在ViewGroup的child view时,在
Action_Down的事件派发时,ViewGroup.onTouch和onTouchEvent仍可以执行,注册View的onClickListener
会对事件消耗的返回值产生影响,表现为:
1.Action_Down事件时,若View/ViewGroup注册了onClickListener,则onTouchEvent返回true
2.Action_Up事件时,通过postDelay异步执行onClickListener,因此其执行时间在Activity.dispatchTouchEvent结束后.
View.onTouchEvent Action_Down时:
在Action_Up时: