转载

Android Touch事件派发流程源码分析

分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时:

正文到此结束
Loading...