这是 Android 触摸系统系列文章的第二部分,第一部分:触摸函数和 View 层次结构深入解析了触摸处理函数以及这些函数如何影响触摸事件在view 层次系统中的流动。本文将用图表展示这些触摸函数如何工作。
这些图表是通过我做的一个示例 app,在 Activity、FrameLayout、ScrollView 和 View 的触摸函数被调用的地方打印日志信息而做出来的。
我们先快速回顾下上一篇文章涉及的函数:
场景1
轻轻点击 View B,没有 view 消费事件
让我们回顾下第一部分的图。注意,View B 是在 View A之后被添加进来的,所以 View B 的 dispatchTouchEvent()
首先被调用;ViewGroup
把触摸事件按照添加顺序的逆序传递给子 view。
场景2
轻轻点击 View B, B 的onTouchEvent()
返回 true。
由于 View B的祖先没有拦截事件,事件一直传递给 View B 的 onTouchEvent()
。由于该函数返回 true,事件在此处停止了,其他 view 的 onTouchEvent()
就不会被调用了。
场景3
轻轻点击 View A,没有 view 消费该事件。
与场景1类似,由于触摸区域没在 View B 范围内, FrameLayout 直接把事件传递给 View A。
场景4
触摸并拖拽 View B,ScrollView 拦截事件并开始滚动。
ScrollView 的 onInterceptTouchEvent()
返回 true,因此它的子 view不会再收到事件通知。ScrollView 的 onTouchEvent()
被调用,该函数也会返回 true,因此事件传递到此停止。
场景5
触摸并拖拽 View B,View B 覆写了 dispatchTouchEvent()
然后 parent.disallowTouchEvent(true)
。View B 的 onTouchEvent()
也返回 true。没有发生滚动。
View B 的所有祖先的 onInterceptTouchEvent()
被忽略了,事件传递在 View B 的 onTouchEvent()
函数这儿停止。ScrollView 不会滚动。
场景6
触摸并拖拽 View B,View B 覆写了 dispatchTouchEvent()
然后 parent.disallowTouchEvent(true)
。View B 的 onTouchEvent()
也返回 false。ScrollView 开始滚动。
View B 的所有祖先的 onInterceptTouchEvent()
被忽略了,但是因为 View B onTouchEvent()
返回 false,不会处理该事件, 事件会向上传递给祖先的 onTouchEvent()
函数。ScrollView 的 onTouchEvent()
被调用并返回 true,意味着它处理了该事件。因此我们会看到滚动,事件传递在此停止。
原文链接:Android Touch System — Part 2: Common Touch Event Scenarios