当前位置: 首页 > news >正文

Android 事件分发学习心得

Android 事件是从Activity向Window、DecorView、ViewGroup、View这样依次传递的事件传递主要搞清楚ViewGroup和View的传递流程:一、View的事件分发流程public boolean dispatchTouchEvent(MotionEvent event) { if (mOnTouchListener ! null (mViewFlags ENABLED_MASK) ENABLED mOnTouchListener.onTouch(this, event)) { return true; } return onTouchEvent(event); }事件传递到子View会先调用其dispatchTouchEvent,1、如果子view注册了OnTouchListener且在onTouch方法里做了事件处理返回true则事件到此消费结束。2、如果上面的if不成立除了1外比如是不可用状态会走view的onTouchEvent方法如果进行了事件处理则返回true否则返回false总结: view的事件分发主要是在dispatchTouchEvent方法里控制如果返回true代表消耗了该事件false代表未消耗该事件。且必须事件的第一个ACTION_DOWN返回了true后续事件才会继续处理否则后续事件不会进入处理二、ViewGroup的事件分发流程public boolean dispatchTouchEvent(MotionEvent ev) { final int action ev.getAction(); final float xf ev.getX(); final float yf ev.getY(); final float scrolledXFloat xf mScrollX; final float scrolledYFloat yf mScrollY; final Rect frame mTempRect; boolean disallowIntercept (mGroupFlags FLAG_DISALLOW_INTERCEPT) ! 0; if (action MotionEvent.ACTION_DOWN) { if (mMotionTarget ! null) { mMotionTarget null; } if (disallowIntercept || !onInterceptTouchEvent(ev)) { ev.setAction(MotionEvent.ACTION_DOWN); final int scrolledXInt (int) scrolledXFloat; final int scrolledYInt (int) scrolledYFloat; final View[] children mChildren; final int count mChildrenCount; for (int i count - 1; i 0; i--) { final View child children[i]; if ((child.mViewFlags VISIBILITY_MASK) VISIBLE || child.getAnimation() ! null) { child.getHitRect(frame); if (frame.contains(scrolledXInt, scrolledYInt)) { final float xc scrolledXFloat - child.mLeft; final float yc scrolledYFloat - child.mTop; ev.setLocation(xc, yc); child.mPrivateFlags ~CANCEL_NEXT_UP_EVENT; if (child.dispatchTouchEvent(ev)) { mMotionTarget child; return true; } } } } } } boolean isUpOrCancel (action MotionEvent.ACTION_UP) || (action MotionEvent.ACTION_CANCEL); if (isUpOrCancel) { mGroupFlags ~FLAG_DISALLOW_INTERCEPT; } final View target mMotionTarget; if (target null) { ev.setLocation(xf, yf); if ((mPrivateFlags CANCEL_NEXT_UP_EVENT) ! 0) { ev.setAction(MotionEvent.ACTION_CANCEL); mPrivateFlags ~CANCEL_NEXT_UP_EVENT; } return super.dispatchTouchEvent(ev); } if (!disallowIntercept onInterceptTouchEvent(ev)) { final float xc scrolledXFloat - (float) target.mLeft; final float yc scrolledYFloat - (float) target.mTop; mPrivateFlags ~CANCEL_NEXT_UP_EVENT; ev.setAction(MotionEvent.ACTION_CANCEL); ev.setLocation(xc, yc); if (!target.dispatchTouchEvent(ev)) { } mMotionTarget null; return true; } if (isUpOrCancel) { mMotionTarget null; } final float xc scrolledXFloat - (float) target.mLeft; final float yc scrolledYFloat - (float) target.mTop; ev.setLocation(xc, yc); if ((target.mPrivateFlags CANCEL_NEXT_UP_EVENT) ! 0) { ev.setAction(MotionEvent.ACTION_CANCEL); target.mPrivateFlags ~CANCEL_NEXT_UP_EVENT; mMotionTarget null; } return target.dispatchTouchEvent(ev); }传递给ViewGroup的dispatchTouchEvent时会先判断是否拦截相关如果进行了拦截: 不往子view传递代码里面通过if条件进行跳过最后target为null然后调用super.dispatchTouchEvent即ViewGroup父类View的dispatchTouchEvent进行处理一般就调用ViewGroup的onTouchEvent事件了。如果不进行拦截: 根据点击位置查找点击区域位于哪一个子View并调用子View的dispatchTouchEvent方法,如果子view dispatchTouchEvent返回true消费了事件则结束如果没有消费事件则会走到target为null,super.dispatchTouchEvent总结: ViewGroup如果拦截则自己在onTouchEvent处理如果不拦截若点击区域子view处理了事件则结束如果不处理则走ViewGroup的onTouchEvent最后归纳: ViewGroup和View 的dispatchTouchEvent返回true代表事件被消费完毕如果返回false代表事件未被消费则继续往上层ViewGroup的onTouch传递这个过程的返回true和false建议追溯源码调试。再次回顾总结: 事件传递到ViewGroup时会先判断是否已经进行onIntercept事件拦截如果拦截了则走onGroup的拦截没有则走子view的dispatchTouchEvent子view的dispatchTouchEvent也同ViewGroup自身最后走的dispatchTouchEventview的dispatchTouchEvent会先判断是否onTouch没有onTouch则走onTouchEvent如果都没有消费则继续到ViewGroup的dispatchEvent如果viewGroup都没有消费则会在父ViewGroup里返回dispatchTouchEvent然后该ViewGroup再递归一遍
http://www.zskr.cn/news/1412079.html

相关文章:

  • Qwopus3.5-27B-v3-GGUF微调全攻略:从数据准备到模型发布的完整流程
  • 2026年 工业仪表厂家热榜:热电阻/热电偶/压力变送器/液位计/差压变送器/温度变送器十大品牌专业评测推荐 - 品牌企业推荐师(官方)
  • 2026最新宜昌市黄金回收白银回收铂金回收店铺实力口碑排行榜TOP5;K金+金条+银条+首饰回收靠谱门店及联系方式推荐 - 前途无量YY
  • 深圳哪家SMT贴片加工厂质量好?哪家性价比高?
  • 2026最新枣庄市黄金回收白银回收铂金回收店铺实力口碑排行榜TOP5;K金+金条+银条+首饰回收靠谱门店及联系方式推荐 - 前途无量YY
  • 告别安装报错:手把手教你为OpenEuler 20.03 LTS SP2 (X86_64)配置正确的官方YUM源
  • DLSS Swapper完整指南:免费一键管理游戏超采样文件,轻松提升显卡性能
  • ViGEmBus深度解析:Windows内核级虚拟手柄驱动技术揭秘
  • 蓝桥杯真题解析:用前缀和5分钟搞定‘两两相乘求和’(附C语言代码)
  • 2026最新张家港市黄金回收白银回收铂金回收店铺实力口碑排行榜TOP5;K金+金条+银条+首饰回收靠谱门店及联系方式推荐 - 前途无量YY
  • SA8155车载开发实战:在QNX上配置I2C驱动连接传感器(附QUB映射表详解)
  • SAP-ABAP:条件判断与循环控制语句(7篇)第六篇:实战演练:用条件判断+循环实现经典算法与业务场景
  • 【Linux网络】彻底搞懂应用层自定义协议与序列化:从底层原理到工业级实战
  • 东莞靠谱的全屋定制制造厂找哪家 - 企业推荐官【官方】
  • Nintendo Switch大气层自制系统:从入门到精通的完整指南
  • 别再只用OLS了!用Python的sklearn实战对比岭回归和Lasso,教你选对正则化参数alpha
  • HTML5 从入门到精通:不止于标签——HTML5 高级特性,小交互无需 JavaScript
  • gbert-large-openmind安全最佳实践:保护你的德语NLP应用免受攻击的终极指南
  • 别再只盯着GPT了!用VQA技术,手把手教你打造一个能‘看懂’医学影像的AI助手
  • 为什么选择GPT-2 Large?深入分析774M参数模型的独特价值
  • 3步掌握WSABuilds:在Windows 10/11上打造完整安卓环境的完整指南
  • 2026最新武夷山市黄金回收白银回收铂金回收店铺实力口碑排行榜TOP5;K金+金条+银条+首饰回收靠谱门店及联系方式推荐 - 前途无量YY
  • 深度解析 gbt7714-bibtex-style:实现GB/T 7714标准的技术实现与最佳实践
  • 免费开源AMD处理器调试工具:SMUDebugTool新手快速上手指南
  • 沙河市黄金回收白银回收铂金回收彩金回收门店优选+2026年最新黄金回收TOP5排行榜及联系方式 - 亦辰小黄鸭
  • SQL Server 2019 Developer版在Win11上的完整配置流水账:从ISO下载到SSMS连接
  • 5分钟掌握:Beyond Compare 5永久激活终极指南
  • 从滤波到优化:手把手拆解VIO算法演进,看OpenVINS、Basalt、DM-VIO如何解决状态估计难题
  • VS2015安装卡在‘安装包丢失或损坏’?别慌,这两个手动修复技巧亲测有效(附原理说明)
  • 厦门市黄金回收白银回收铂金回收彩金回收门店优选+2026年最新黄金回收TOP5排行榜及联系方式 - 亦辰小黄鸭