Android好奇宝宝_08_乱侃触摸事件传递

讲解触摸事件传递原理的网上有一大把,有从源码角度讲的,有从实际例子角度讲的。我这里呢只是记录下自己的理解,讲的可能没其他大牛透彻,有错误的跪求评论指正。

直接上图,对照图解和文字来分析触摸事件的传递。

(1)乱七八糟图解版:

(2)看图说话:

(2.1)上图并不包含Activity,Activity没有onInterceptTouchEvent方法,默认实现都是直接往下传递。

(2.2)讲解3个触摸事件控制方法的含义及其返回值的意义:

<1>onInterceptTouchEvent

onInterceptTouchEvent是ViewGroup特有的方法,Activity和View并没有此方法,它的作用是用于拦截触摸事件不再传递给子View(Activity和View并没有子View,所以没有此方法很符合逻辑),默认实现不拦截。如果拦截的话子View将完全接受不到触摸事件,子View的任何相关触摸事件的方法都不会被调用。(注:有例外情况我会在后面再说)(有特殊情况)

返回true:

表示拦截触摸事件,不继续调用子View的dispatchTouchEvent方法,直接调用自己的onTouchEvent方法。(有特殊情况)

返回false:

表示不拦截事件,继续去调用子View的dispatchTouchEvent。

<2>dispatchTouchEvent

用于分派触摸事件,注意是分派事件,而不是处理事件,这个方法应该做的是决定事件的传递方向,而不是处理消费掉触摸事件。

返回true:

表示自己要消费这个事件,但并不是马上消费,而是如果其子View没人消费的话,则自己消费。事件还是会继续往下传递的,只是在往上传递过程中如果还能到达自己的话,那么就会去消费这个事件。

返回false:

表示自己不消费这个事件,如果同时onTouchEvent也返回false表示不消费这个事件的话,就会继续往上传递给parent的onTouchEvent。

<3>onTouchEvent

用于处理事件,如果你想处理触摸事件并做出相应的动作,那么应该在这个方法中进行。

返回true:

表示自己想消费这个事件,并且马上生效,即刻消费,事件传递停止。

返回false:

表示自己不想消费这个事件,同时检查dispatchTouchEvent之前若是返回了true,就会发现:哎呀,我之前说子View没人处理的话,那么就我来处理。好吧,我要遵守诺言,就交给我处理吧,不要再传递了。

注意dispatchTouchEvent和onTouchEvent返回true的区别:

dispatchTouchEvent是没人消费的话就交给我消费,你们都没人要啊,那就给我吧,各位大爷真是好人啊。

onTouchEvent是我现在就要消费,其它人都没份了,都干嘛干嘛去,就是这么霸气,就是这么任性。

(2.3)传递过程中那些可能发生的事

触摸事件的第一个接收者总是Activity,Activity一般不会去消费触摸事件,而是直接传递给处于该触摸事件范围的View树集合。在View树中等级位置对应在触摸事件中的位置,即越外层的View,就位于越顶层,而其child则位于底层。即Activity在最顶层,然后接下来是容器控件,最后的View在最底层。

在一般情况下:

事件先从上往下,经过每一个dispatchTouchEvent。到达最后一个View时,调用其onTouchEvent,开始从下往上的传递过程,经过每一个onTouchEvent,这是没任何View想要消费触摸事件的情况。

可能发生的几个转折点:

<1>在从上往下的过程中,如果某个View的onInterceptTouchEvent返回了true,表示拦截事件,事件不会继续往下传递,而是直接调用这个View的onTouchEvent,注意这并不意味着这个View消费了这个事件,只是拦截了这个事件继续往下传递,剥夺了子View的消费权,提前开始从下往上的过程而已,是否由它消费还要看其onTouchEvent的返回值是否为true。(有特殊情况)

<2>在从下往上的过程中,如果某个View的onTouchEvent返回了true,表示自己想要消费这个事件,事件不会继续往上传递,事件传递结束。

<3>还是在从下往上的过程中,如果某个View在之前的dispatchTouchEvent方法返回了true,表示在之前这个View表明如果所有子View都不消费这个事件的话,那么就让我来消费,事件不会继续往上传递,事件传递结束。

(所有子View都不消费这个事件意味着所有子View的dispatchTouchEvent和onTouchEvent都返回了false,不然事件早被消费且传递结束了,根本不会再到达自己。)

<4>这个比较少用,某个子View调用了parent的requestDisallowInterceptTouchEvent方法,表示请求parent不要拦截事件,这种情况下parent的onInterceptTouchEvent返回了true也拦截不了事件,即让onInterceptTouchEvent方法失效,这就是上面3个标记了(有特殊情况)所说的特殊情况。

(2.4)记忆功能

记忆功能是指,如果某个View消费了Down事件,那么接下来的Move和Up等事件还是会从Activity顶层向下传递,但是传递到这个View时,即使这个View并没有用onInterceptTouchEvent方法来拦截事件,事件还是会被拦截,直接由该View处理。即如果一个View消费了Down事件,则接下来的Move和Up事件也会交给它消费。

这么做的原因是:一般情况下单一的触摸事件并不能形成有效的动作。比如一个拖动动作需要Down事件和连续的Move事件,点击动作至少需要一个Down事件和Up事件。把单一的触摸事件分派给不同的View,往往形成不了有意义的动作,所以加入了这个记忆功能来减少事件的传递。

(3)随便说点

理解触摸事件的传递一般是为了解决触摸事件发生冲突的情况,处理触摸事件冲突时要注意一点:

我们要处理的是由谁来处理触摸事件,而不是去修改消费这个事件的View应该去怎么处理。

有点拗口是吧,再说白一点就是我们应该控制谁来处理,而不是控制怎么去处理,每个View都有自己的处理逻辑,我们不应该去修改它。

举个栗子:

手指左右拖动不了ViewPager时,我们想得应该是怎么在手指左右拖动的情况下让ViewPager能获得触摸事件的消费权,而不要管接受到触摸事件后怎么让ViewPager随着手指滚动,这个功能ViewPager自己已经实现了,你把触摸事件给它,它就能滚。

好了,本篇完结,建议对触摸事件传递机制不熟悉的自己写个例子打印些Log日志验证一下,再百度谷歌下一下常见的触摸冲突及其解决办法。

求赞求评论求指点啊!!!

时间: 2024-12-29 05:20:13

Android好奇宝宝_08_乱侃触摸事件传递的相关文章

Android ViewGroup 触摸事件传递机制

引言 上一篇博客我们学习了Android View 触摸事件传递机制,不了解的同学可以查看Android View 触摸事件传递机制.今天继续学习Android触摸事件传递机制,这篇博客将和大家一起探讨ViewGroup的触摸事件传递机制. 示例 示例代码如下: public class MainActivity extends ActionBarActivity { private String TAG = "MainActivity"; private MyViewGroup pa

Android View 触摸事件传递机制

PS:以现在的眼光看以前写的博客感觉写的很烂,或许或一段时间再看现在的博客会有同样的感觉.所以每时每刻都去学习,去发现和理解新的东西. 引言 由于之前写的一篇关于Android事件传递顺序的博客质量太差,可能是理解不到位的原因,故最近又花了许多时间再次去看Android源码,看完之后有了新的理解,所以打算重新整理这篇博客.理解Android触摸事件传递机制有助于日后的开发以及自定义一些手势效果等.注意:这篇博客是基于Android2.0源码来分析的,不管老版本还是新版本的Android,其内部触

Android 控件的触摸事件传递与处理

了解Android控件的触摸事件传递与处理对我们日常开发中自定义控件和触摸事件冲突解决有重大意义.Android控件的触摸事件传递和处理主要有以下几个方法,下面一一介绍. 一.与触摸事件有关的几个方法 boolean dispatchTouchEvent(MotionEvent ev);                                                                                               接收到触摸事件时,是否

Android好奇宝宝_04_一个有3个功能的Adapter

感觉Android好奇宝宝这个系列是脱离不了ListView和GridView了... 这一篇呢来分享点好东西 一个自定义Adapter,可以快速实现三个功能: (1)自动缓存处理 好吧,这个功能不是我实现的.我只是照搬鸿洋大大的,我会简单说下,不过还是请先看下他的原文,再来看我添加的两个功能,传送门 (2)支持item的不同布局 提供一个接口来通过position和该position的数据来设置不同的布局 (3)局部刷新 只刷新指定item的某个子View,避免一直调用notifyDataSe

iOS 和 Android 触摸事件传递

先看2篇文章,写得很好,都是咱们博客园的博文 ios 触摸事件传递 http://www.cnblogs.com/Quains/p/3369132.html android 触摸事件传递 http://www.cnblogs.com/superlcr/p/3946034.html 读完这2篇文章,可以发现ios和android对触摸事件的处理的大体思路是一致的,都是从根view开始,遍历检测子view,找到适合的view触发具体事件.2个平台都具备分发触摸事件,拦截触摸事件传递的机能. 下面盗用

【android学习】安卓设备实现触摸事件的监听,跨进程事件注入

最近想实现触摸屏的事件记录,并且分别做时间戳标记,类似于adb shell 下的getevent/setevent,查了很多资料,下面是一些总结. 实现方法: 1.利用onclick方法等.这种方法只能用于自己的Activity和View中,如果要检测其他Activity,比如键盘就不行了. 2.从linux内核入手.在事件分发前截获事件,可以对任意Activity实现事件捕获. android触摸事件的流程: http://blog.csdn.net/sunnyfans/article/det

android中View点击和触摸事件的处理

android中的事件类型分为按键事件和屏幕触摸事件,Touch事件是屏幕触摸事件的基础事件,有必要对它进行深入的了解. 一个最简单的屏幕触摸动作触发了一系列Touch事件:ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_MOVE...->ACTION_MOVE->ACTION_UP 当屏幕中包含一个ViewGroup,而这个ViewGroup又包含一个子view,这个时候android系统如何处理Touch事件呢?到底 是View

Android好奇宝宝_番外篇_看脸的世界_08

废话少说,先上效果图: (左侧的图片是我用window画图软件1分钟画的,所以就不要嫌丑了,You can you up no bb.) 这是我发过最挫的效果图了,不过这是由于没有图片素材导致的,就不要在意这些细节了,知道实现原理后完全可以发挥你的想象去实现更美观的效果. 这个效果也是有开源库的,不过我又把名字给忘了,不过我记得原理,于是就试着自己写了一下. 其实原理很简单,我在另一篇博客(一个有吃豆人删除动画的ListView)也说过了,这一篇当做兑换那些年少轻狂不更事时许下的诺言(是不是瞬间

触摸事件传递与响应者链条

触摸事件传递 •发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中 •UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发送事件给应用程序的主窗口(keyWindow) •主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件,这也是整个事件处理过程的第一步 •触摸事件的传递是从父控件传递到子控件,如果父控件不能接收触摸事件,那么子控件就不可能接收到触摸事件 响应者链条 1.如果view的控制器存在,就传递给控制器: