android的事件分发机制
参考文章图解 Android 事件分发机制这个文章很早我就看过了但是只是知道是这个流程具体怎么操作点击事件如何传递依然有点迷甚至连这个流程图是否正确都不敢持肯定态度所以今天就来用代码实现下毕竟眼见为实嘛。debug过程太繁琐这里就不一步步贴了直接上带注释的结果1、点击viewgroup时事件分发流程activity.dispatchTouchEvent { super } 》viewgroup.dispatchTouchEvent { super } 》viewgroup.onTouchEvent { super } 》viewgroup.setOnClickListener2、点击view时事件分发流程activity.dispatchTouchEvent { super } 》viewgroup.dispatchTouchEvent { super } 》viewgroup.onInterceptTouchEvent { super } 》 view.dispatchTouchEvent { super } 》view.onTouchEvent { super } 》view.setOnClickListener3、activity的dispatchTouchEvent返回true或者false时事件分发流程activity.dispatchTouchEvent { true/false } 》无4、viewgroup的dispatchTouchEvent返回true时事件分发流程activity.dispatchTouchEvent { super } 》viewgroup.dispatchTouchEvent { true } 》无5、viewgroup的dispatchTouchEvent返回false时事件分发流程activity.dispatchTouchEvent { super } 》activity.onTouchEvent { super } 》无6、viewgroup的onInterceptTouchEvent返回true时事件分发流程activity.dispatchTouchEvent { super } 》viewgroup.dispatchTouchEvent { super } 》viewgroup.onInterceptTouchEvent { true } 》 viewgroup.onTouchEvent { super } 》viewgroup.setOnClickListener7、viewgroup的onInterceptTouchEvent返回false时事件分发流程和super一样activity.dispatchTouchEvent { super } 》viewgroup.dispatchTouchEvent { super } 》viewgroup.onInterceptTouchEvent { false } 》 view.dispatchTouchEvent { super } 》view.onTouchEvent { super } 》view.setOnClickListener8、view的dispatchTouchEvent返回true时事件分发流程activity.dispatchTouchEvent { super } 》viewgroup.dispatchTouchEvent { super } 》viewgroup.onInterceptTouchEvent { super } 》 view.dispatchTouchEvent { true } 》无9、view的dispatchTouchEvent返回false时事件分发流程activity.dispatchTouchEvent { super } 》viewgroup.dispatchTouchEvent { super } 》viewgroup.onTouchEvent { super } 》viewgroup.setOnClickListener10、view的onTouchEvent返回true时事件分发流程activity.dispatchTouchEvent { super } 》viewgroup.dispatchTouchEvent { super } 》viewgroup.onInterceptTouchEvent { super } 》 view.dispatchTouchEvent { super } 》view.onTouchEvent { true } 》无11、view的onTouchEvent返回false时事件分发流程activity.dispatchTouchEvent { super } 》viewgroup.dispatchTouchEvent { super } 》viewgroup.onTouchEvent { super } 》viewgroup.setOnClickListener12、viewgroup的onTouchEvent返回true时事件分发流程activity.dispatchTouchEvent { super } 》viewgroup.dispatchTouchEvent { super } 》viewgroup.onTouchEvent { true } 》无13、viewgroup的onTouchEvent返回false时事件分发流程activity.dispatchTouchEvent { super } 》activity.onTouchEvent { super } 》无14、activity的onTouchEvent返回true或者false时事件分发流程activity.onTouchEvent { true/false } 》无super.dispatchTouchEvent也是返回true、false为什么和直接设置 dispatchTouchEvent{ true、false }效果完全不一样呢这个消费是什么意思dispatchTouchEvent 返回 true 只代表这次 MotionEvent 被消费了但它不等于点击事件onClick一定发生。这两件事在源码里是分开的。true事件被消费不再向父级回传本次调用直接结束false事件没被消费上交父 ViewGroup 的 onTouchEventsuper.dispatchTouchEvent()走默认分发逻辑拦截判断 → 遍历子 View → 自身 onTouchEventsuper.dispatchTouchEvent()返回 true 是因为内部的 onTouchEvent 返回了 true或者子 View 消费了。整个事件序列走完了完整的 U 型链路viewgroup的onInterceptTouchEvent是不是有点多余当 ViewGroup 通过onInterceptTouchEvent返回 true 拦截事件时原先正在处理事件的子 View 会收到一个ACTION_CANCEL告诉它事件序列被抢走了请你重置状态。如果你直接在dispatchTouchEvent里 return true系统不会自动给子 View 补发 CANCEL。子 View 会永远卡在按下状态——按钮高亮清不掉、RecyclerView 的滚动状态无法复位。dispatchTouchEvent方法有有一整套分发遍历流程如果直接设置就需要手动配置这些逻辑所以onInterceptTouchEvent才会被抽出单独来管是否拦截具体到代码上如何设置拦截外部拦截法父主导父在onInterceptTouchEvent的 MOVE 中根据滑动方向决定拦截内部拦截法子主导子在dispatchTouchEvent里根据业务逻辑调用requestDisallowInterceptTouchEvent调用后父 ViewGroup 的onInterceptTouchEvent在后续 MOVE/UP 中会被跳过/** * 事件分发测试 * activity层 */ public class MainActivity extends AppCompatActivity { private LinearlayoutViewGroup mViewGroup; private TextViewView mView; Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mViewGroup findViewById(R.id.mViewGroup); mView findViewById(R.id.mView); mViewGroup.setOnClickListener(v - { Log.e(点击, ViewGroup点击事件触发); }); mView.setOnClickListener(v - { Log.e(点击, View点击事件触发); }); } /** * event 普通点击会触发三次ACTION_DOWN、ACTION_MOVE、ACTION_UP * 这里只讨论 ACTION_UP 的传递流程 * return super 默认方法 点击viewgroup和view时传递到viewgroup 的 dispatchTouchEvent 方法 * return true/false 事件到这里结束 */ Override public boolean dispatchTouchEvent(MotionEvent event) { if (event.getAction() 1) Log.e(点击, activity-dispatchTouchEvent); return super.dispatchTouchEvent(event); } /** * return super/true/false activity的点击事件触发事件到这里结束 */ Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() 1) Log.e(点击, activity-onTouchEvent); return super.onTouchEvent(event); } }/** * viewGroup层 */ public class LinearlayoutViewGroup extends LinearLayout { public LinearlayoutViewGroup(Context context) { super(context); } public LinearlayoutViewGroup(Context context, Nullable AttributeSet attrs) { super(context, attrs); } public LinearlayoutViewGroup(Context context, Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public LinearlayoutViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } /** * return super 默认方法点击viewgroup时传递给自己的 onTouchEvent 方法。点击view时传递给自己的 dispatchTouchEvent 方法 * return true 事件到这里结束 * return false 事件传递给acivity的 onTouchEvent 方法 */ Override public boolean dispatchTouchEvent(MotionEvent event) { if (event.getAction() 1) Log.e(点击, ViewGroup-dispatchTouchEvent); return super.dispatchTouchEvent(event); } /** * 判断是否拦截了某个事件 * return super/false 默认方法点击view时传递到view的 dispatchTouchEvent 方法 * return true 事件传递给自己的 onTouchEvent 方法 */ Override public boolean onInterceptTouchEvent(MotionEvent event) { if (event.getAction() 1) Log.e(点击, ViewGroup-onInterceptTouchEvent); return super.onInterceptTouchEvent(event); } /** * return super 默认方法点击viewgroup时触发viewgroup的 setOnClickListener 方法 * return true 事件到这里结束 * return false 事件传递到activity的 onTouchEvent 方法 */ Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() 1) Log.e(点击, ViewGroup-onTouchEvent); return super.onTouchEvent(event); } }/** * view层 */ //SuppressLint(AppCompatCustomView) public class TextViewView extends View { public TextViewView(Context context) { super(context); } public TextViewView(Context context, Nullable AttributeSet attrs) { super(context, attrs); } public TextViewView(Context context, Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public TextViewView(Context context, Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } /** * return super 默认方法点击view时传递给自己的 onTouchEvent 方法。 * return true 事件到这里结束 * return false 事件传递给viewgroup的 onTouchEvent 方法 */ Override public boolean dispatchTouchEvent(MotionEvent event) { if (event.getAction() 1) Log.e(点击, View-dispatchTouchEvent); return super.dispatchTouchEvent(event); } /** * return super 默认方法点击view时触发view的 setOnClickListener 方法 * return true 事件到这里结束 * return false 事件传递给viewgroup的 onTouchEvent 方法 */ Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() 1) Log.e(点击, View-onTouchEvent); return super.onTouchEvent(event); } }

相关新闻

OneMore:如何让OneNote笔记管理效率提升160%的终极免费插件

OneMore:如何让OneNote笔记管理效率提升160%的终极免费插件

OneMore:如何让OneNote笔记管理效率提升160%的终极免费插件 【免费下载链接】OneMore A OneNote add-in with simple, yet powerful and useful features 项目地址: https://gitcode.com/gh_mirrors/on/OneMore 你是否经常在OneNote中感到功能受限&#xff1…

2026/7/24 20:04:32阅读更多 →
【GNSS】多GNSS系统定位对比:单系统与融合系统精度分析

【GNSS】多GNSS系统定位对比:单系统与融合系统精度分析

论文引用信息 本文内容基于以下SPIE会议论文: Zixia Shang, “Off-line Data Processing Based on GNSSLOGGER, GNSS System Positioning Data Quality and Accuracy Analysis,” Fourth International Conference on Geology, Mapping, and Remote Sensing (ICGMR…

2026/7/24 20:04:32阅读更多 →
抖音直播数据采集实战指南:3步搭建实时监控系统

抖音直播数据采集实战指南:3步搭建实时监控系统

抖音直播数据采集实战指南:3步搭建实时监控系统 【免费下载链接】DouyinLiveWebFetcher 抖音直播间网页版的弹幕数据抓取(2025最新版本) 项目地址: https://gitcode.com/gh_mirrors/do/DouyinLiveWebFetcher 在当今直播电商和内容创作…

2026/7/24 20:04:32阅读更多 →
单开单控电路

单开单控电路

上图电路工作原理:火线(L)先经过漏电保护器,接到墙壁开关的进线端;零线(N)从保护器直接拉到灯泡尾部接线柱。开关断开时,火线被切断,灯泡没有电流,灯不亮。按…

2026/7/24 21:36:48阅读更多 →
RT-Thread快速入门(九)之总结与知识图谱

RT-Thread快速入门(九)之总结与知识图谱

前言 从第一篇"线程创建与删除"到第八篇"事件集",我们走完了 RT-Thread 内核的完整学习路径。本文将对整个系列进行系统性总结,整理成一张清晰的知识图谱,方便回顾和查阅。 RT-Thread快速入门(一&#xff0…

2026/7/24 21:36:48阅读更多 →
FigmaCN完整指南:5分钟实现Figma全界面中文汉化,设计师工作效率翻倍

FigmaCN完整指南:5分钟实现Figma全界面中文汉化,设计师工作效率翻倍

FigmaCN完整指南:5分钟实现Figma全界面中文汉化,设计师工作效率翻倍 【免费下载链接】figmaCN 中文 Figma 插件,设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 你是否曾因为Figma的英文界面而犹豫不决&…

2026/7/24 21:36:48阅读更多 →
三极与钳式电磁铁|微型多维磁场精密发生设备

三极与钳式电磁铁|微型多维磁场精密发生设备

在微磁学实验、薄膜材料测试、微观磁各向异性研究、精密器件标定等场景中,常规单维度大磁场电磁铁存在体积大、维度单一、无法实现面内/面外复合磁场的短板。小型精密电磁铁凭借结构紧凑、维度灵活、磁场精准、适配微观样品测试的优势,成为微观磁性能研究…

2026/7/24 21:36:48阅读更多 →
3个炉石传说macOS玩家必知的智能助手技巧:HSTracker完全指南

3个炉石传说macOS玩家必知的智能助手技巧:HSTracker完全指南

3个炉石传说macOS玩家必知的智能助手技巧:HSTracker完全指南 【免费下载链接】HSTracker A deck tracker and deck manager for Hearthstone on macOS 项目地址: https://gitcode.com/gh_mirrors/hs/HSTracker 你是否曾在激烈的炉石传说对战中,因…

2026/7/24 21:36:48阅读更多 →
5分钟快速上手DeepL翻译插件:让浏览器变成你的多语言助手

5分钟快速上手DeepL翻译插件:让浏览器变成你的多语言助手

5分钟快速上手DeepL翻译插件:让浏览器变成你的多语言助手 【免费下载链接】deepl-chrome-extension A DeepL Translator Chrome extension 项目地址: https://gitcode.com/gh_mirrors/de/deepl-chrome-extension 还在为阅读外文网页而烦恼吗?Deep…

2026/7/24 21:34:47阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/24 0:58:53阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/24 0:58:53阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/24 0:58:53阅读更多 →
我的编程之路:第一篇博客

我的编程之路:第一篇博客

大家好,我是一名编程初学者,同时这也是我编程学习之路上的第一篇博客。在这里,我想要向大家介绍我的一些想法和规划。a.自我介绍我是一个刚刚接触编程的新手,目前在学习c语言,我对编程世界充满了强烈的好奇。当然&…

2026/7/24 0:00:06阅读更多 →
【LeetCode 54】螺旋矩阵

【LeetCode 54】螺旋矩阵

问题描述: 解法: 1、模拟(参考自【LeetCode 54】螺旋矩阵-CSDN博客) int *spiralOrder(int **matrix, int matrixSize, int *matrixColSize, int *returnSize) {static const int dirs[4][2] {{0, 1}, {1, 0}, {0, -1}, {-1, …

2026/7/24 0:00:06阅读更多 →
2026 WAIC:模型隐身、智能体疯野,厂商竞赛聚焦办公场景与商业闭环

2026 WAIC:模型隐身、智能体疯野,厂商竞赛聚焦办公场景与商业闭环

知春路不相信模型领先今年WAIC大会,昔日AI六小龙来了五家,分别是Kimi、阶跃星辰、Minimax、百川智能、零一万物。连放弃基模的百川和零一万物都来了,唯一缺席的竟是近几个月来风光无限的智谱。(DeepSeek一直不参加)WAI…

2026/7/24 0:00:06阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/23 22:58:43阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/24 19:00:40阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/24 19:00:40阅读更多 →