Android随笔-事件分发机制 一、整体流程U 型传递二、三个核心方法1. dispatchTouchEvent — 事件分发入口所有 View 都有是事件分发的总入口。// Activity.dispatchTouchEvent()publicbooleandispatchTouchEvent(MotionEventev){if(ev.getAction()MotionEvent.ACTION_DOWN){onUserInteraction();// 用户交互回调}// 先交给 Window 处理if(getWindow().superDispatchTouchEvent(ev)){returntrue;// 被消费}// 没人消费Activity 自己处理returnonTouchEvent(ev);}// ViewGroup.dispatchTouchEvent() — 核心逻辑publicbooleandispatchTouchEvent(MotionEventev){booleanhandledfalse;if(onFilterTouchEventForSecurity(ev)){finalintactionev.getAction();// 每次 DOWN 重置状态if(actionMotionEvent.ACTION_DOWN){cancelAndClearTouchTargets(ev);resetTouchState();}// 1. 检查是否拦截finalbooleanintercepted;if(actionMotionEvent.ACTION_DOWN||mFirstTouchTarget!null){interceptedonInterceptTouchEvent(ev);}else{interceptedtrue;// 没有 TouchTarget直接拦截}// 2. 如果不拦截找子 View 分发if(!intercepted){ViewchildfindTouchTarget(...);if(child!null){if(child.dispatchTouchEvent(ev)){mFirstTouchTargetchild;// 记录消费者handledtrue;}}}// 3. 如果没子 View 消费自己处理if(mFirstTouchTargetnull){handledsuper.dispatchTouchEvent(ev);// 调用 View 的 dispatch}}returnhandled;}// View.dispatchTouchEvent()publicbooleandispatchTouchEvent(MotionEventevent){booleanresultfalse;// 1. 先调用 OnTouchListener如果设置了if(mOnTouchListener!null(mViewFlagsENABLED_MASK)ENABLEDmOnTouchListener.onTouch(this,event)){resulttrue;// Listener 消费了}// 2. 如果 Listener 没消费调用 onTouchEventif(!resultonTouchEvent(event)){resulttrue;}returnresult;}2. onInterceptTouchEvent — 事件拦截仅 ViewGroup 有决定是否拦截事件。// ViewGroup.onInterceptTouchEvent()publicbooleanonInterceptTouchEvent(MotionEventev){// 默认返回 false不拦截returnfalse;}// 典型拦截逻辑ScrollView 滑动拦截OverridepublicbooleanonInterceptTouchEvent(MotionEventev){switch(ev.getAction()){caseMotionEvent.ACTION_DOWN:mLastYev.getY();mIsScrollingfalse;returnfalse;// DOWN 不拦截让子 View 有机会点击caseMotionEvent.ACTION_MOVE:floatdyev.getY()-mLastY;if(Math.abs(dy)mTouchSlop){mIsScrollingtrue;returntrue;// 滑动时拦截}returnfalse;caseMotionEvent.ACTION_UP:caseMotionEvent.ACTION_CANCEL:returnmIsScrolling;}returnfalse;}3. onTouchEvent — 事件消费所有 View 都有处理具体事件。// View.onTouchEvent()publicbooleanonTouchEvent(MotionEventevent){// 如果不可点击直接返回 falseif((mViewFlagsENABLED_MASK)DISABLED){returnclickable;}// 处理各种点击效果if(clickable||longClickable){switch(event.getAction()){caseMotionEvent.ACTION_UP:// 触发 performClick() → 调用 OnClickListener.onClick()if((mPrivateFlagsPFLAG_PRESSED)!0){performClick();}break;caseMotionEvent.ACTION_DOWN:// 检查长按checkForLongClick(0);break;caseMotionEvent.ACTION_CANCEL:removeTapCallback();removeLongPressCallback();break;}returntrue;// 可点击消费事件}returnfalse;}三、事件处理优先级同一个 View 内事件处理优先级onTouch() (OnTouchListener)→ return true: 直接消费不调用 onTouchEvent→ return false: 继续往下onTouchEvent()→ return true: 消费事件→ 内部调用 performClick()onClick() (OnClickListener)→ 在 ACTION_UP 触发→ 前提是 onTouchEvent 返回 true优先级onTouch onTouchEvent onClick// 设置 OnTouchListener 会拦截 onClickview.setOnTouchListener(newView.OnTouchListener(){OverridepublicbooleanonTouch(Viewv,MotionEventevent){// return true: 消费事件onClick 不会触发// return false: 不消费继续传给 onTouchEvent → onClickreturntrue;}});四、事件序列与状态机完整事件序列ACTION_DOWN → 确定消费者↓ACTION_MOVE (0~N次) → 直接给已确定的消费者↓ACTION_UP / ACTION_CANCEL → 结束序列状态机规则事件行为DOWN 到达重置所有状态重新决定消费者MOVE 到达直接给已确定的消费者不重新遍历UP/CANCEL 到达给消费者重置状态关键规则DOWN 事件决定后续流向一旦某个 View 消费了 DOWN后续 MOVE/UP 都给它拦截发生在 MOVE父 View 在 MOVE 时拦截 → 子 View 收到 CANCEL → 后续事件都给父requestDisallowInterceptTouchEvent(true)子 View 禁止父 View 拦截DOWN 除外五、常见场景处理1. ScrollView 嵌套 RecyclerView// ScrollView 在 MOVE 时拦截OverridepublicbooleanonInterceptTouchEvent(MotionEventev){switch(ev.getAction()){caseMotionEvent.ACTION_DOWN:returnfalse;// 不拦截 DOWNcaseMotionEvent.ACTION_MOVE:if(isVerticalScroll(ev)){returntrue;// 纵向滑动拦截}returnfalse;}returnfalse;}// 拦截后 RecyclerView 收到 CANCEL停止滑动2. ViewPager 嵌套 ListView// 通过 dx/dy 判断滑动方向OverridepublicbooleanonInterceptTouchEvent(MotionEventev){switch(ev.getAction()){caseMotionEvent.ACTION_DOWN:mLastXev.getX();mLastYev.getY();returnfalse;caseMotionEvent.ACTION_MOVE:floatdxMath.abs(ev.getX()-mLastX);floatdyMath.abs(ev.getY()-mLastY);if(dxdy){returntrue;// 横向滑动ViewPager 拦截}returnfalse;// 纵向滑动ListView 处理}returnfalse;}3. Button 在 ScrollView 中点击: Button 消费 DOWN → 后续 MOVE/UP 给 Button滑动: ScrollView 在 MOVE 时拦截 → Button 收到 CANCEL→ 后续 MOVE/UP 给 ScrollView六、自定义 ViewGroup 拦截示例publicclassMyViewGroupextendsViewGroup{privatefloatmLastY;privatebooleanmIsScrollingfalse;OverridepublicbooleanonInterceptTouchEvent(MotionEventev){switch(ev.getAction()){caseMotionEvent.ACTION_DOWN:mLastYev.getY();mIsScrollingfalse;returnfalse;// 不拦截 DOWN让子 View 有机会点击caseMotionEvent.ACTION_MOVE:floatdyev.getY()-mLastY;if(Math.abs(dy)10){// 滑动阈值mIsScrollingtrue;returntrue;// 拦截滑动}returnfalse;caseMotionEvent.ACTION_UP:caseMotionEvent.ACTION_CANCEL:returnmIsScrolling;}returnfalse;}OverridepublicbooleanonTouchEvent(MotionEventevent){// 处理滑动逻辑switch(event.getAction()){caseMotionEvent.ACTION_MOVE:scrollBy(0,(int)(mLastY-event.getY()));mLastYevent.getY();break;}returntrue;// 消费事件}}七、核心口诀规则说明DOWN 决定消费者从 Activity 逐级下传找到消费 DOWN 的 ViewMOVE/UP 直接给不重新遍历直接给已确定的消费者拦截发生在 MOVE父 View 在 MOVE 时拦截子 View 收到 CANCELonTouch onTouchEvent onClick优先级顺序事件序列不可分割DOWN → [MOVE…] → UP/CANCEL 必须同一个 View 消费

相关新闻

最新新闻

AD7490与PIC18F4680嵌入式信号采集系统设计指南

AD7490与PIC18F4680嵌入式信号采集系统设计指南

1. AD7490与PIC18F4680的硬件选型解析在嵌入式信号采集系统中,ADC芯片和微控制器的选型直接决定了系统的性能上限。AD7490作为ADI公司推出的16位逐次逼近型(SAR)ADC,具有以下核心特性:分辨率与采样率:16位分辨率下最高1MSPS采样率…

2026/7/11 3:10:41
鲸占GEO:品牌出海如何布局AI平台搜索优化,抢占精准长尾流量?

鲸占GEO:品牌出海如何布局AI平台搜索优化,抢占精准长尾流量?

不出海,就出局。但出海之后,你的品牌能被海外用户「搜」到吗?一、品牌出海的新战场:AI 搜索引擎中国品牌出海的热潮持续升温,但一个残酷的现实是:90% 的品牌网站,月均自然搜索流量不足 500。为什…

2026/7/11 3:10:41
Excel 2010 VLOOKUP与IF函数组合:5种常见错误值排查与数据匹配方案

Excel 2010 VLOOKUP与IF函数组合:5种常见错误值排查与数据匹配方案

Excel 2010 VLOOKUP与IF函数组合实战:5种错误值深度解析与高效数据匹配方案数据匹配的痛点与函数组合价值在日常办公中,数据查找与匹配是Excel用户最常遇到的任务场景。根据行业调研,超过78%的中级用户每周至少使用VLOOKUP函数3次以上&#x…

2026/7/11 3:10:41
iOS激活锁绕过终极指南:使用applera1n免费解锁A9-A11设备

iOS激活锁绕过终极指南:使用applera1n免费解锁A9-A11设备

iOS激活锁绕过终极指南:使用applera1n免费解锁A9-A11设备 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n 你是否曾经遇到过这样的情况:购买了一台二手iPhone,却因为…

2026/7/11 3:10:41
Unity游戏转型微信小游戏:架构设计与性能优化实战指南

Unity游戏转型微信小游戏:架构设计与性能优化实战指南

1. 项目概述:为什么Unity游戏转型微信小游戏是门“技术活”?如果你是一名Unity开发者,手头有一个运行流畅的PC或移动端项目,现在老板或客户要求你把它搬到微信小游戏上,你的第一反应是什么?是觉得“不就是换…

2026/7/11 3:10:41
【清华代码熊】Qwen/GLM/DeepSeek等基座模型 OPD 技术总结

【清华代码熊】Qwen/GLM/DeepSeek等基座模型 OPD 技术总结

📌 今天主题:回顾Qwen/Mimo/GLM/DeepSeek各家基座模型中的 On-Policy Distillation(OPD)技术。​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

2026/7/11 3:05:41

月新闻