Android Touch事件传递机制解析

Android Touch事件传递机制全面解析(从WMS到View树) 转眼间近一年没更新博客了,工作一忙起来,很难有时间来写博客了,由于现在也在从事Android开发相关的工作,因此以后的博文也会更多地专注于这一块。 这篇文章准备从源码层面为大家带来Touch事件的传递机制,我这里分析的源码时Android4.4的。说到分析源码,光看肯定是不行的,一定要亲自去跟,并且要边跟边思考,所以在下一篇中,会有一个Demo来为大家详细分析源码的走向。 阅读详情

Android Touch事件传递机制解析

没事逛论坛,无意间看到了一篇非常不错的帖子,转载如下:

 

开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把android touch机制好好看了一下,呵呵。。

android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法:

1)public boolean dispatchTouchEvent(MotionEvent ev)          这个方法用来分发TouchEvent

2)public boolean onInterceptTouchEvent(MotionEvent ev)         这个方法用来拦截TouchEvent

3)public boolean onTouchEvent(MotionEvent ev)                 这个方法用来处理TouchEvent

注意:不是所有的View的子类,很多教程都说的是所有的View的子类,只有可以向里面添加View的控件才需要分发,比如TextView它本身就是最小的view了,所以不用再向它的子视图分发了,它也没有子视图了,所以它没有dispatch和Intercept,只有touchEvent。

 

device-2012-03-24-084959.png

说明: 白色为最外层,它占满整个屏幕;

红色为中间区域,属于白色中的一层;

黑色为中心区域,必于红色中的一层。

注意:他们本质上是:LinearLayout,而不是RelativeLayout或者其它布局。

1.由中心区域处理touch事件

布局文件如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="fill_parent"
  4.     android:layout_height="fill_parent"
  5.     android:orientation="vertical">
  6.     <com.kris.touch.widget.TouchView
  7.         android:id="@+id/view_out"
  8.         android:layout_width="fill_parent"
  9.         android:layout_height="fill_parent"
  10.         android:background="#fff"
  11.         android:gravity="center">
  12.             <com.kris.touch.widget.TouchView
  13.                 android:id="@+id/view_mid"
  14.                 android:layout_width="300px"
  15.                 android:layout_height="400px"
  16.                 android:background="#f00"
  17.                 android:gravity="center">
  18.             <com.kris.touch.widget.TouchView
  19.                 android:id="@+id/view_center"
  20.                 android:layout_width="150px"
  21.                 android:layout_height="150px"
  22.                 android:background="#000"
  23.                 android:gravity="center"
  24.                 android:clickable="true">
  25.             </com.kris.touch.widget.TouchView>
  26.             </com.kris.touch.widget.TouchView>
  27.     </com.kris.touch.widget.TouchView>
  28. </LinearLayout>

复制代码

注意:                android:clickable="true"  

接下来我们看一下打印的日志:

1111.png

结合是上面的日志,我们可以看一下ACTION_DOWN事件处理流程:

a0dfaa98gb7f95585f7a2&690.png

说明:

首先触摸事件发生时(ACTION_DOWN),由系统调用Activity的dispatchTouchEvent方法,分发该事件。根据触摸事件的坐标,将此事件传递给out的dispatchTouchEvent处理,out则调用onInterceptTouchEvent 判断事件是由自己处理,还是继续分发给子View。此处由于out不处理Touch事件,故根据事件发生坐标,将事件传递给out的直接子View(即middle)。

Middle及Center中事件处理过程同上。但是由于Center组件是clickable 表示其能处理Touch事件,故center中的onInterceptTouchEvent方法将事件传递给center自己的onTouchEvent方法处理。至此,此Touch事件已被处理,不继续进行传递。

2.没有指定谁会处理touch事件

布局文件如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="fill_parent"
  4.     android:layout_height="fill_parent"
  5.     android:orientation="vertical">
  6.     <com.kris.touch.widget.TouchView
  7.         android:id="@+id/view_out"
  8.         android:layout_width="fill_parent"
  9.         android:layout_height="fill_parent"
  10.         android:background="#fff"
  11.         android:gravity="center">
  12.             <com.kris.touch.widget.TouchView
  13.                 android:id="@+id/view_mid"
  14.                 android:layout_width="300px"
  15.                 android:layout_height="400px"
  16.                 android:background="#f00"
  17.                 android:gravity="center">
  18.             <com.kris.touch.widget.TouchView
  19.                 android:id="@+id/view_center"
  20.                 android:layout_width="150px"
  21.                 android:layout_height="150px"
  22.                 android:background="#000"
  23.                 android:gravity="center">
  24.             </com.kris.touch.widget.TouchView>
  25.             </com.kris.touch.widget.TouchView>
  26.     </com.kris.touch.widget.TouchView>
  27. </LinearLayout>

复制代码

注意:只是比上一次的布局少了android:clickable="true" 
接下来我们看一下打印的日志

2222.png

结合是上面的日志,我们可以看一下ACTION_DOWN事件处理流程:

a0dfaa98gb7f9559d8155&690.png

说明:

事件处理流程大致同上,区别是此状态下,所有组件都不会处理事件,事件并不会被center的onTouchEvent方法“消费”,则事件会层层逆向传递回到Activity,若Activity也不对此事件进行处理,此事件相当于消失了(无效果)。

对于后续的move、up事件,由于第一个down事件已经确定由Activity处理事件,故up事有由Activity的dispatchTouchEvent直接分发给自己的onTouchEvent方法处理。

代码请看最后的附件

总结:

1) Touchevent 中,返回值是 true ,则说明消耗掉了这个事件,返回值是 false ,则没有消耗掉,会继续传递下去,这个是最基本的。2) 事件传递的两种方式: 
隧道方式:从根元素依次往下传递直到最内层子元素或在中间某一元素中由于某一条件停止传递。 
冒泡方式:从最内层子元素依次往外传递直到根元素或在中间某一元素中由于某一条件停止传递。 android对Touch Event的分发逻辑是View从上层分发到下层(dispatchTouchEvent函数)类似于隧道方式,然后下层优先开始处理Event(先mOnTouchListener,再onTouchEvent)并向上返回处理情况(boolean值),若返回true,则上层不再处理。类似于冒泡方式 
于是难题出现了,你若把Touch Event都想办法给传到上层了(只能通过返回false来传到上层),那么下层的各种子View就不能处理后续事件了。而有的时候我们需要在下层和上层都处理Touch事件

举个例子,ViewFlipper用来检测手势,在内部我们放几个Image,有点像gallery的效果,也就是左右滑动切换图片,但是图片有时候我们希望可以放大缩小!这样就会存在ViewFlipper里面需要touch事件,而在image里面也需要一个touch事件(当图片大小屏幕边界的时候可以拖动图片,而不是左右切换图片)。

我首先的思路是着手于事件回传的方式,研究了n久,实际了n久,都没达到自己想要的结果 ,我甚至于把gallery和gallery3D 的源码下载下来看了N久也没办法去解决,在这里随便说一下gallery吧,gallery虽然在这个效果,但是人家并不是ViewFlipper加image这样来实现的,人家是像游戏这样用一个view来统一处理的,我们可以简单的理解成自定义了一个控件,这样touch事件想怎么处理就怎么处理,不过就是逻辑复杂了,我们想偷懒就没办法了,呵呵。。。

最后不停的试啊试啊,想到一个可行的方案,但是我觉得不是很靠谱,也就是:我们在ViewFlipper这里,我们先把所有的touch都截取到,然后在他的onTouchEvent中,我们先调用imageview的onTouchEvent事件,如果返回true,证明这个事件,imageview要用,那么ViewFlipper就当什么事都没发生,如果imageview返回的false,则调用自己的touchEvent.伪代码如下:

  1. //自定义一个MyViewFlipper 继承于ViewFlipper,并且实现onTouchEvent方式,

复制代码

我觉得他不靠谱的原因为: 1. 他打断了android的原有的机制,不是很提倡。 
2. 得试先知道ViewFlipper里面的控件,或者说通过某种路径能获取到 
3. 如果ViewFlipper里面的控件多了,就蛋疼了

好了,如果有什么意见或者建议,大家一起讨论。

QGC二次开发实战指南(一):从零构建自定义地面站界面 本文详细介绍了QGC二次开发实战指南,从零开始构建自定义地面站界面。通过QT和QML技术结合MAVLINK协议,开发者可以打造适合特定业务场景的无人机监控系统,提升操作效率与用户体验。文章包含环境搭建、界面设计、数据绑定等完整开发流程,是QGC二次开发的实用教程。 阅读详情

相关推荐

ADS仿真功率放大器实例学习笔记

ADS仿真功率放大器实例学习笔记

qq_36521926的博客 1万+

STM32F103C6T6移植RTOS避坑指南

第二次:就是复刻实验,为这篇文章准备素材的时候,走到最后一步,也是不闪灯。通过搜索关键词“unknown type name ‘__forceinline’”得知,这是由于新版的Keil5使用的编译器是ARM Compiler 6(AC6),但是RTOS中stm32f相关的代码太老,大都是AC5流行时期开发,导致无法使用AC6编译。虽然是一个简单的小实验,但是能用上最近学的知识解决问题,确实加强了学习RTOS的信心,值得好好写篇文章纪念一下:一来鼓励自己继续前进,二来也给其他有需要的人提供力所能及的帮助。

guofeizhi的博客 857

激光及激光器超全细节&原理总结

本文详细展示了激光、激光器、PN结、半导体激光器、光纤激光器的原理和应用;

guangwulv的博客 5344

Android Touch事件传递详解

首先将TouchView的onTouchEvent返回值改为true,和上一组日志做对比分析,这一组数据中两个touch事件都有4条记录,形态完全对称非常漂亮,touch事件从MainActivity开始,到TouchView消亡,而上一组数据的touch事件还有一个回溯的过程,这是因为这次TouchView的onTouchEvent方法返回了true,将这个事件给消费了。(img-OKG6iluo-1713728437024)]就是在自定义的灰色ViewGroup中放入一个黑色的孩子节点。

2401_84123557的博客 778

【OpenBMC 系列】4.启动流程 使用qume模拟ast2600-evb

1.安装openbmc适配的qume 2.启动bmc 3.使用bmc web

AiFool的博客 4458

IPD(集成产品开发)管理之道

IPD,是集成产品开发(Integrated Product Development)的缩写,它是集成了众多管理模型和理论、众多企业最佳管理实践的一整套体系,可以帮助企业快速响应市场变化、缩短产品上市时间、减少资源浪费、提高生产力,最终取得商业成功。IPD的思想最早来源于美国PRTM公司出版的《产品及生命周期优化法》一书中,该书详细描述了IPD模式所包含的各个方面。但IPD在中国的普及,源于IBM和华为的推行使用。IPD作为一套先进的产品研发管理模式,其成功的基础是功能部门和各团队之间的密切配合。

钢镚·真的博客 2712

探索Hammer.js Touch Emulator:模拟触摸事件,助力移动开发

探索Hammer.js Touch Emulator:模拟触摸事件,助力移动开发 touchemulatorEmulate touch input on your desktop项目地址:https://gitcode.com/gh_mirrors/to/touchemulator 是一个强大的工具,它允许开发者在桌面环境下模拟触摸事件,从而在没有实际移动设备的情况下测试和调试基于Hammer....

gitblog_00002的博客 698

影像组学分析流程中,图像分割前要做的事(图像预处理)

在InputVolume中无法找到自己想要重采样的序列,这时可以检查一下序列的Volume type是不是MRMLMulti。这时,Volume type将由MRMLMulti改为Scaler,随后即可在3D slicer中完成Resample Scaler Volume。2.1、重采样:通过3Dslicer中的Resample Scaler Volume实现。具体设置参数:spacing(1,1,1),Interpolation选择Bspline。2、图像预处理:重采样和标准化。

weixin_45011313的博客 3724

android 事件处理

用到的例子工程介绍:在viewGroup中加入子view,即LinerLayout中存在一子view,在MyLinerLayout中重写了 dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent 在MyTestView中重写了dispatchTouchEvent、onTouchEvent。 分别研究各种返回值对事件传递的路径影响。 My

leesidong的专栏 1万+

【雷达】基于matlab合成孔径雷达干涉测量(InSAR)时序分析【含Matlab源码 9037期】

合成孔径雷达干涉测量(InSAR)时序分析 完整代码,包运行;可提供运行操作视频!适合小白!

订阅付费专栏Matlab(奶茶价版),可赠送奶茶价版付费专栏指定代码1份; 159

Xilinx DDR3 MIG IP核设计--汇总导航

快速上手Xilinx DDR3 IP核----汇总篇

孤独的单刀 2万+

Android Touch事件传递机制解析 X2

MotionEvent事件在onInterceptTouchEvent()、onTouchEvent()中的传递顺序  onInterceptTouchEvent()用于处理事件并改变事件的传递方向。处理事件这个不用说了,你在函数内部编写代码处理就可以了。而决定传递方向的是返回值,返回为false时事件会传递给子控件的onInterceptTouchEvent();返回值为true时

jhydn的专栏 573

Cesium 实现气象(温度,降水,风速)可视化详细代码实现

本教程介绍了使用Cesium实现气象数据可视化的方法,主要包括:1) 搭建Cesium开发环境;2) 三种核心气象要素的展示技术:温度热力图(基于颜色渐变和点密度)、降水区域填充(矩形着色)和风速风向(粒子系统);3) 数据集成方案,包括模拟数据生成和API对接;4) 高级功能如3D温度柱和时间序列动画;5) 性能优化策略,如数据聚合和LOD控制。教程提供了完整的代码示例,从基础配置到视觉效果实现,帮助开发者构建交互式气象可视化应用。

专注AI大模型,软件混淆,授权 1846

【转】Android Touch事件传递机制解析

Android Touch事件传递机制解析 android系统中的每个View的子类都具有下面三个和TouchEvent处理密切相关的方法: 1)public boolean dispatchTouchEvent(MotionEvent ev) 这个方法用来分发TouchEvent 2)public boolean onInterceptTouchEvent(MotionEvent...

dijue6306的博客 135

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

上一篇: Android Studio常见问题整理
下一篇: Android 中与 Touch 事件详解
ProbuINg
博客等级 码龄14年 10粉丝 77原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值