View结构
简介
-
Android 的
View是树形结构的,View可能会重叠在一起,当触摸的地方有多个View都可以响应的时候由 事件分发机制 决定该由谁响应。
示意图

DecorView
- 主题颜色和标题栏等内容就是显示在
DecorView中的。
PhoneWindow
-
Window是一个抽象类,是所有视图的最顶层容器,视图的外观和行为都归他管,而PhoneWindow是Window的唯一实现类。
事件分发、拦截与消费
| 类型 | 相关方法 | Activity | ViewGroup | View |
|---|---|---|---|---|
| 事件分发 | dispatchTouchEvent() |
√ | √ | √ |
| 事件拦截 | onInterceptTouchEvent() |
X | √ | X |
| 事件消费 | onTouchEvent() |
√ | √ | √ |
-
Activity和View都是没有 事件拦截 的,因为:-
Activity作为原始的事件分发者,如果Activity拦截了事件会导致整个屏幕都无法响应事件。 -
View最为事件传递的最末端,要么消费掉事件,要么不处理进行回传,无需 事件拦截 。
-
事件分发流程
流程简介
-
事件正向传递 :
View是树形结构的,基于这样的结构,事件收集之后最先传递给Activity,依次向下传递:Activity -> PhoneWindow -> DecorView -> ViewGroup -> ... -> View
-
事件反向回传 :如果最后分发到
View,如果这个View也没有处理事件,那么会发生 事件反向回传 ,最终传回给Activity,如果最后Activity也没有处理,本次事件才会被抛弃:Activity <- PhoneWindow <- DecorView <- ViewGroup <- ... <- View
情景分析
示意图

情景一:点击View1区域但没有View消费事件。

情景二:点击View1区域且事件被View1消费

情景三:点击View1区域但事件被ViewGroupA拦截

总结
- 从根往叶传递时决定是否拦截:
onInterceptTouchEvent()是从根部开始的,根据返回值判断事件是否拦截。 - 从叶往根回传时决定是否消费掉:
onTouchEvent()是从叶部开始的,根据返回值来判断事件是否消费。