news 2026/7/24 20:06:26

android的事件分发机制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
android的事件分发机制

参考文章:图解 Android 事件分发机制

这个文章很早我就看过了,但是只是知道是这个流程,具体怎么操作,点击事件如何传递依然有点迷,甚至连这个流程图是否正确都不敢持肯定态度,所以今天就来用代码实现下,毕竟眼见为实嘛。

debug过程太繁琐这里就不一步步贴了,直接上带注释的结果

1、点击viewgroup时,事件分发流程:
activity.dispatchTouchEvent { super } ==》viewgroup.dispatchTouchEvent { super } ==》viewgroup.onTouchEvent { super } ==》viewgroup.setOnClickListener

2、点击view时,事件分发流程:
activity.dispatchTouchEvent { super } ==》viewgroup.dispatchTouchEvent { super } ==》viewgroup.onInterceptTouchEvent { super } ==》 view.dispatchTouchEvent { super } ==》view.onTouchEvent { super } ==》view.setOnClickListener

3、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.setOnClickListener

7、viewgroup的onInterceptTouchEvent返回false时,事件分发流程:(和super一样)
activity.dispatchTouchEvent { super } ==》viewgroup.dispatchTouchEvent { super } ==》viewgroup.onInterceptTouchEvent { false } ==》 view.dispatchTouchEvent { super } ==》view.onTouchEvent { super } ==》view.setOnClickListener

8、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.setOnClickListener

10、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.setOnClickListener

12、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 的 onTouchEvent

  • super.dispatchTouchEvent():走默认分发逻辑(拦截判断 → 遍历子 View → 自身 onTouchEvent)

  • super.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); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/24 20:06:16

品牌出海发稿哪家靠谱?深度拆解朝闻通全链路服务

一、新闻发稿行业发展脉络与企业核心需求 1.1 新闻发稿市场发展三阶段演进 新闻发稿是企业品牌建设、舆情口碑维护、市场公信力背书的基础性核心服务。伴随媒体行业数字化、智能化转型升级,国内新闻发稿市场历经三轮迭代变革,在运营模式、服务效率、传播…

作者头像 李华
网站建设 2026/7/24 20:03:53

MCU基础

目录 1.CPU的基本结构和运行机制 1.1 ALU 1.2 Register Files 1.3 Control Unit 2.堆栈的概念 3.ARM体系结构 3.1 ARM的发展过程 3.2 ARM Cortex M Register Files(Programmers Model) 4.中断 4.1 中断的概念和机制 4.2 中断的允许和禁止、现…

作者头像 李华
网站建设 2026/7/24 20:02:49

系统架构设计师考试:高效备考策略与资源推荐

639 | 系统架构设计师考试:高效备考策略与资源推荐 考系统架构设计师,就像参加一场马拉松。 不是比谁起跑快,而是比谁能坚持到最后。 一、考试概览 考试信息 ┌───────────────────────────────────────────────────…

作者头像 李华
网站建设 2026/7/24 20:02:22

如何快速选择最佳行情服务器:mootdx智能连接优化指南

如何快速选择最佳行情服务器:mootdx智能连接优化指南 【免费下载链接】mootdx 通达信数据读取的一个简便使用封装 项目地址: https://gitcode.com/GitHub_Trending/mo/mootdx 在金融数据分析和量化交易中,获取实时、准确的行情数据至关重要。moot…

作者头像 李华
网站建设 2026/7/24 19:59:15

深度解析TI ADS8353/7853 ADC评估套件:从硬件设计到性能测试实战

1. 项目概述与核心价值在精密数据采集系统的设计过程中,选型一颗合适的模数转换器(ADC)仅仅是第一步。更关键、也更具挑战性的是,如何将这颗ADC芯片的理论性能,在真实的电路板上完整地“复现”出来。芯片手册上那些令人…

作者头像 李华