当我们的手指在屏幕上滑动形成原始数据,经过驱动的处理,再经过系统服务的选择,最终来到我们写的应用。

Touch事件的前世今生还是比较复杂的,涉及到多方代码。

这里我们只关注应用层中java的代码。

ViewRootImpl.setView这个方法是核心。

InputChannel 
--> WindowInputEventReceiver   
--> InputStage(So many child class, 传递到View是在ViewPostImeInputStage)
-->  View.dispatchPointerEvent 
--> DecorView.dipatchTouchEvent(每个Activity和Dialog的window的直接View是DecorView) 
--> call Activity.dispatchTouchEvent 
--> call DecorView.superDispatchTouchEvent (前面这两步像扔飞去来一样,又回到自己怀里了) 
--> ViewGroup.dispatchTouchEvent

到最后一步我们就熟悉了,dispatchTouchEvent onInterceptTouchEvent onTouchEvent。

我们可以将View在脑海中分成一层层的,父View为一层,子View为下层,这样子整个视图,自上到下,可以形象一点。

用语言简单叙述一下每一层逻辑就是

if onInterceptTouchEvent then
    self.onTouchEvent
else
    childViews.dispatchTouchEvent
end

当然实际要比这复杂的多。

每一层View都要经过这个逻辑,touch事件的传递会呈现一个 V 字形。

这里有几种情况。

  • onInterceptTouch在DOWN事件的时候就为false,之后在这层View就不会判断onInterceptTouch了,直接调用onTouchEvent
  • onInterceptTouch在DOWN事件的时候为true,但是在MOVE的时候被intercept了,会给原先传递事件的子View传递一个CANCEL事件,之后的MOVE,UP事件就直接onTouchEvent了,可以理解成 大V 变 小v 了
  • 还有就是如果子View的onTouchEvent的处理中调用了requestDisallowInterceptTouchEvent(true)的话,在MOVE事件的传递过程中,是不会判断onInterceptTouch方法的,也就是不能被拦截了,接下来MOVE事件一直都会发给子View

还有要记录的一点是mFirstTouchTarget,这个变量会再DOWN事件时,如果子View接受了事件mFirstTouchTarget会记住处理的View,mFirstTouchTarget相当于一个单向不循环链表,至于为什么是个链表,是因为多指触摸到多个View的情况