Android 的事件分发、传递、处理机制

本文详细解析了Android中点击事件的传递与处理机制,包括ViewGroup的事件拦截逻辑、事件分发过程及View处理事件的具体步骤。通过源码分析帮助读者深入理解Android事件系统的运作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.点击事件传递规则

1.1 ViewGroup 中逻辑

  1. 对于一个根 ViewGroup,点击事件产生后,首先传递给它,调用它的 dispatchTouchEvent 方法

  2. 如果这个 ViewGroup 的 onInterceptTouchEvent 返回 true ,表示它要拦截该事件,接着事件会交由 该 ViewGroup 处理,即调用 它的 onTouchEvent 方法

  3. 如果 onInterceptTouchEvent 返回 false,事件会传递给它的 子View,接着 子View 调用它的 dispatchTouchEvent 方法。

1.2 onTouchEvent 返回 false

事件传递,遵循规则如下:Activity –> Window –> View(顶级View)

如果一个 View(无子View) 的 onTouchEvent 返回 false,那么它父容器的 onTouchEvent 会被调用,一次类推,如果所有的元素都不处理该事件,那么这个事件最终会传给 Activity 处理,即 Activity 的 ontouchEvent 会被调用。

1.3 总结,更好地理解整个传递机制

这里写图片描述
这里写图片描述
这里写图片描述

2.顶级View对点击事件的分发过程

2.1 大致逻辑

如果事件能够传递给当前View,那么此方法一定会被调用

返回结果受当前View 的 onTouchEvent 和下级 View 的 dispatchTouchEvent 方法的影响表示是否消耗当前事件

这里写图片描述

2.2 当前View是否拦截点击事件源码分析

这里写图片描述

这里写图片描述

结论

  • 当ViewGroup 决定拦截事件后,那么后续的点击事件都会交给它处理并且不再调用它的 onInterceptTouchEvent 方法

  • onInterceptTouchEvent 不是每次事件都会被调用,如果想提前处理所有的点击事件,要选择 dispatchTouchEvent 方法,只要能传递给当前 View ,他每次都会被调用

  • FLAG_DISALLOW_INTERCEPT 可以用于处理滑动冲突

2.3 ViewGroup 不拦截时事件分发的源码

首先会遍历 ViewGroup 的所有子元素,然后判断子元素是否可以接收点击事件(子元素是否在播动画 && 点击事件的坐标是否落在子元素的区域内),如果某个子元素满足这两个条件,事件就会传递给它来处理。

这里写图片描述

如果子元素的 dispatchTouchEvent 返回 true,暂不考虑如何在子元素内部怎么分发,mFirstTouchTarget 就会被赋值同时跳出 for 循环

这里写图片描述

如果子元素的 dispatchTouchEvent 返回 false,ViewGroup 就会把事件分发给下一个子元素(如果有)

  • Activity.dispatchTouchEvent 返回 true |fasle 事件只在 Activity 的 dispatchTouchEvent 进行处理。

如果遍历所有的子元素后事件都没有被合适的处理,这包含两种情况,1:ViewGroup 没有子元素,2:子元素处理了点击事件,但是 dispatchTouchEvent 中返回了 false (一般是因为子元素在 onTouchEvent 中返回了 false),这就验证了下面这句话:

这里写图片描述

另外,在这两种情况下,ViewGroup 会自己处理点击事件

这里写图片描述
这里写图片描述

注意第三个参数 child 为 null , 2.3 一开始的代码里有分析,它会调用

super.dispatchTouchEvent(event)

很显然,这里会转到 View 的 dispatchTouchEvent 方法,即点击事件交由 View 来处理

  • View.dispatchTouchEvent 返回super.dispatchTouchEvent(ev); 事件会传递给当前View的 onTouchEvent 进行处理;

  • ViewGroup.dispatchTouchEvent 返回super.dispatchTouchEvent(ev); 事件会传递给当前ViewGroup的 onInterceptTouchEvent 进行处理;

3. View(不含ViewGroup)处理事件逻辑

右侧的是 onTouchEvent 中的 onClick 方法,也在下面

这里写图片描述

onTouchEvent 方法中的逻辑:

这里写图片描述

4.事件拦截 onInterceptTouchEvent

onInterceptTouchEvent 的事件拦截逻辑如下:

  • 如果 onInterceptTouchEvent 返回 true,则表示将事件会被拦截,事件最终在当前ViewGroup的 onTouchEvent 进行处理;

  • 如果 onInterceptTouchEvent 返回 false,则表示将事件没被拦截,事件会被传递到子 View上,再由子 View 的 dispatchTouchEvent来开始这个事件的分发;

  • 如果 onInterceptTouchEvent 返回 super.onInterceptTouchEvent(ev),事件默认不会被拦截,处理方式同返回false一样。

5.事件响应 onTouchEvent

onTouchEvent 的事件响应逻辑如下:

  • 如果 onTouchEvent返回了 true 则会接收并消费该事件。

  • 如果 onTouchEvent返回了 false 那么这个事件会从当前 View 向上传递,并且都是由上层 View 的 onTouchEvent 来接收,

    如果传递到上面的 onTouchEvent 也返回 false,这个事件就会“消失”,而且接收不到下一次事件。

  • 如果返回 super.onTouchEvent(ev);

    Activity.super.onTouchEvent(ev); 默认 返回 false

    ViewGroup.super.onTouchEvent(ev); 默认 返回 false

    View.super.onTouchEvent(ev); Clickable 或 LongClickable 一个为true,就默认 返回 true,不管它是不是 disable 状态

6. 事件分发机制 完整流程图

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值