Android事件分发机制实例验证

Android事件分发机制实例验证



欢迎转载,转载请注明原文出处http://blog.csdn.net/lavor_zl/article/details/51198634,谢谢。

事件分发机制的学习主要来自下面两篇博文:

  • Android事件传递机制
  • Android 编程下 Touch 事件的分发和消费机制

    这两篇博文写的非常好,但是看完了这两篇博文还是有一些不理解的地方,缺少一丝明悟。于是亲自写下几种情况的代码,来看事件分发的结果,从而验证事件分发机制。验证完后瞬间有了一种明悟,感觉豁然开朗。纸上学来终觉浅,绝知此事要躬行。

我的程序是在MainActivity中有一个自定义的MyLayout布局,MyLayout布局下面有一个自定义的MyButton。


情况1

PS:表格中super代表返回父类中同名的方法,–代表没有此方法,无返回值代表该方法的返回类型是void。

点击非MyButton区域,结果如下:

点击MyButton区域,结果如下:

通过这两个结果我们可以发现事件是从上往下分发的Activity->ViewGroup->View。

但是这两个结果还有一个不对应的地方,那就是第一个结果的MyLayout的onInterceptTouchEvent方法在抬起时没有执行,而第二个结果执行了。这是因为ViewGroup中的dispatchTouchEvent方法只会在按下时或者该事件会继续往下分发时才会调用onInterceptTouchEvent方法。

情况2

点击非MyButton区域,结果如下:

点击MyButton区域,结果如下:

情况2的输出结果明显比情况1少,这是因为MyLayout中onInterceptTouchEvent方法和onTouchEvent方法都是在ViewGroup中的dispatchTouchEvent方法中调用的,而情况二下面MyLayout中dispatchTouchEvent方法的返回值是false,不是super.dispatchTouchEvent(ev),没有调用ViewGroup中的dispatchTouchEvent方法。因为返回值是false,所以会将事件返回给上级的onTouchEvent方法进行消费而不会继续往下分发,因此MyLayout中的onTouch方法和onClick方法也不会执行。这样就导致情况2下面点击非MyButton区域与点击MyButton区域的结果相同了。

情况3

点击非MyButton区域,结果如下:

点击MyButton区域,结果如下:

情况3的输出结果明显比情况2还少一条,这是因为情况3中MyLayout中dispatchTouchEvent方法的返回值是true,事件将由MyLayout中dispatchTouchEvent方法消费,不会向上传递由上级的onTouchEvent方法进行消费,所以情况3的输出结果比情况2还少1条。

情况4

点击非MyButton区域,结果如下:

点击MyButton区域,结果如下:

情况4的输出结果与情况1完全一样,这是因为MyLayout中的onInterceptTouchEvent方法中的返回值一个是false,一个是super.dispatchTouchEvent(event),而ViewGroup的dispatchTouchEvent方法中什么都没有,就是返回值是false。

情况5

点击非MyButton区域,结果如下:

点击MyButton区域,结果如下:

情况5点击非MyButton区域和点击MyButton区域的结果相同,这是因为MyLayout中的onInterceptTouchEvent方法的返回值是true,表示将事件进行拦截,并将事件交给当前View的onTouchEvent进行处理,事件不会继续往下分发了。

情况6

点击非MyButton区域,结果如下:

点击MyButton区域,结果如下:

情况6中点击点击非MyButton区域与情况1中点击点击非MyButton区域结果不同,这是因为情况6中的MyLayout中onTouchEvent方法返回值是false,表示当前View解决不了,会把事件向上传递交给上级的onTouchEvent方法处理。我们发现在抬起事件时,MainActivity没有将事件分发给MyLayout,这是因为在之前的按下事件时,MainActivity将事件分发给MyLayout,而MyLayout之前没有将事件处理成功,所以在抬起事件时,MainActivity不会将事件分发给MyLayout。但是在下次抬起事件时,MainActivity还是会将将事件分发给MyLayout,这是因为记忆MyLayout之前没有将事件处理成功元素在每次抬起事件时,会通过父级的dispatchTouchEvent方法清空。

情况7

点击非MyButton区域,结果如下:

点击MyButton区域,结果如下:

情况7中点击点击非MyButton区域比情况1中点击点击非MyButton区域的结果少1条,这是因为MyLayout中的onTouchEvent方法的返回值是true,表示当前View会接受并消费该事件,但是此时并没有调用View中的onTouchEvent方法,不调用该方法Click事件就无法被响应。

情况8

点击非MyButton区域,结果如下:

点击MyButton区域,结果如下:

情况8中点击点击非MyButton区域比情况1中点击点击非MyButton区域的结果少,这是因为MyLayout中的onTouch方法返回值是true,若某个View的的onTouch方法返回值是true,则结束,若返回值是false则调用该View的onTouchEvent方法。

情况9

点击非MyButton区域,结果如下:

点击MyButton区域,结果如下:

情况10

点击非MyButton区域,结果如下:

点击MyButton区域,结果如下:

总结

该实例验证刚好验证了Android 编程下 Touch 事件的分发和消费机制里面的Touch 事件分析。

下面将该博文的Touch 事件分析部分引用出来:

事件分发:public boolean dispatchTouchEvent(MotionEvent ev)



Touch 事件发生时 Activity 的 dispatchTouchEvent(MotionEvent ev) 方法会以隧道方式(从根元素依次往下传递直到最内层子元素或在中间某一元素中由于某一条件停止传递)将事件传递给最外层 View 的 dispatchTouchEvent(MotionEvent ev) 方法,并由该 View 的 dispatchTouchEvent(MotionEvent ev) 方法对事件进行分发。dispatchTouchEvent 的事件分发逻辑如下:

  • 如果 return true,事件会分发给当前 View 并由 dispatchTouchEvent 方法进行消费,同时事件会停止向下传递;
  • 如果 return false,事件分发分为两种情况:

    * 如果当前 View 获取的事件直接来自 Activity,则会将事件返回给 Activity 的 onTouchEvent 进行消费;

    * 如果当前 View 获取的事件来自外层父控件,则会将事件返回给父 View 的 onTouchEvent 进行消费。

  • 如果返回系统默认的 super.dispatchTouchEvent(ev),事件会自动的分发给当前 View 的 onInterceptTouchEvent 方法。

事件拦截:public boolean onInterceptTouchEvent(MotionEvent ev)



在外层 View 的 dispatchTouchEvent(MotionEvent ev) 方法返回系统默认的 super.dispatchTouchEvent(ev) 情况下,事件会自动的分发给当前 View 的 onInterceptTouchEvent 方法。onInterceptTouchEvent 的事件拦截逻辑如下:

  • 如果 onInterceptTouchEvent 返回 true,则表示将事件进行拦截,并将拦截到的事件交由当前 View 的 onTouchEvent 进行处理;
  • 如果 onInterceptTouchEvent 返回 false,则表示将事件放行,当前 View 上的事件会被传递到子 View 上,再由子 View 的 dispatchTouchEvent 来开始这个事件的分发;
  • 如果 onInterceptTouchEvent 返回 super.onInterceptTouchEvent(ev),事件默认会被拦截,并将拦截到的事件交由当前 View 的 onTouchEvent 进行处理。

事件响应:public boolean onTouchEvent(MotionEvent ev)



在 dispatchTouchEvent 返回 super.dispatchTouchEvent(ev) 并且 onInterceptTouchEvent 返回 true 或返回 super.onInterceptTouchEvent(ev) 的情况下 onTouchEvent 会被调用。onTouchEvent 的事件响应逻辑如下:

  • 如果事件传递到当前 View 的 onTouchEvent 方法,而该方法返回了 false,那么这个事件会从当前 View 向上传递,并且都是由上层 View 的 onTouchEvent 来接收,如果传递到上面的 onTouchEvent 也返回 false,这个事件就会“消失”,而且接收不到下一次事件。
  • 如果返回了 true 则会接收并消费该事件。
  • 如果返回 super.onTouchEvent(ev) 默认处理事件的逻辑和返回 false 时相同。

情况6,7,8还有一些总结之外的知识点,要注意。

时间: 2024-11-05 13:44:12

Android事件分发机制实例验证的相关文章

Android事件分发机制详解:史上最全面、最易懂

前言 Android事件分发机制是每个Android开发者必须了解的基础知识 网上有大量关于Android事件分发机制的文章,但存在一些问题:内容不全.思路不清晰.无源码分析.简单问题复杂化等等 今天,我将全面总结Android的事件分发机制,我能保证这是市面上的最全面.最清晰.最易懂的 本文秉着"结论先行.详细分析在后"的原则,即先让大家感性认识,再通过理性分析从而理解问题: 所以,请各位读者先记住结论,再往下继续看分析: 文章较长,阅读需要较长时间,建议收藏等充足时间再进行阅读 目

【朝花夕拾】Android自定义View篇之(六)Android事件分发机制(中)从源码分析事件分发逻辑及经常遇到的一些“诡异”现象

前言 转载请注明,转自[https://www.cnblogs.com/andy-songwei/p/11039252.html]谢谢! 在上一篇文章[[朝花夕拾]Android自定义View篇之(五)Android事件分发机制(上)Touch三个重要方法的处理逻辑][下文简称(五),请先阅读完(五)再阅读本文],我们通过示例和log来分析了Android的事件分发机制.这些,我们只是看到了现象,如果要进一步了解事件分发机制,这是不够的,我们还需要透过现象看本质,去研究研究源码.本文将从源码(基

Android事件分发机制的学习

最近被Android事件分发机制折磨的很烦躁,网上各种博客资料看完觉得还是得自己写一篇,一方面加深理解,另一方面希望能帮助到也同样在学习相关知识的童鞋们. 话不多说,直接开整. 当用户的手指点击到屏幕,便是整个事件的开始. 首先获取到该事件的是view层的控制者Activity,具体怎么获得我们不得而知,在此也不追究,而继续我们的主题.Activity获得事件后便执行它自身的方法: public boolean dispatchTouchEvent(MotionEvent ev) { if (e

Android事件分发机制

转载请注明出处:http://blog.csdn.net/chziroy/article/details/44401615 要理解Android事件分发机制,首先得了解几个概念,也算是总结,如果暂时看不懂也无妨,本文会讲解这几个问题. 1,点击屏幕,首先事件的传递从Activity的dispatchTouchEvent()方法开始. 2,关于Android事件分发机制,相关方法的方法有三个:onTouchEvent(),dispatchTouchEvent(),还有onInterceptTouc

图解 Android 事件分发机制

首发原文:http://mp.weixin.qq.com/s?__biz=MzI0MjE3OTYwMg==&mid=2649548149&idx=1&sn=709149df682c7d3a6e453c9ef0626a1f&chksm=f1180e08c66f871eb2e7e39e057a5b090214fd71adcd98aa36b3d7fcecf77ad5d08138c50131#rd 在Android开发中,事件分发机制是一块Android比较重要的知识体系,了解并熟

Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9097463 其实我一直准备写一篇关于Android事件分发机制的文章,从我的第一篇博客开始,就零零散散在好多地方使用到了Android事件分发的知识.也有好多朋友问过我各种问题,比如:onTouch和onTouchEvent有什么区别,又该如何使用?为什么给ListView引入了一个滑动菜单的功能,ListView就不能滚动了?为什么图片轮播器里的图片使用Button而不用Ima

android 事件分发机制(图文详解)

在Android开发中,事件分发机制是一块Android比较重要的知识体系,了解并熟悉整套的分发机制有助于更好的分析各种点击滑动失效问题,更好去扩展控件的事件功能和开发自定义控件,同时事件分发机制也是Android面试必问考点之一,如果你能把下面的一些事件分发图当场画出来肯定加分不少.废话不多说,总结一句:事件分发机制很重要. Android 事件分发流 关于Android 事件分发机制网上的博文很多,但是很多都是写个Demo然后贴一下输出的Log或者拿源码分析,然后一堆的注释和说明,如果用心的

Android事件分发机制详解(1)----探究View的事件分发

探究View的事件分发 在Activity中,只有一个按钮,注册一个点击事件 [java] view plaincopy button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Log.d("TAG", "onClick execute"); } }); 如果在需要一个触摸事件 [java] view plaincopy button.setO

Android事件分发机制详解(2)----分析ViewGruop的事件分发

首先,我们需要 知道什么是ViewGroup,它和普通的View有什么区别? ViewGroup就是一组View的集合,它包含很多子View和ViewGroup,是Android 所有布局的父类或间接父类. 但ViewGroup也是一个View,只不过比起View,它可以包含子View和定义布局参数的功能. 现在,通过一个Demo演示Android中ViewGroup的事件分发机制. 首先我们来自定义一个布局,命名为MyLayout,继承自LinearLayout,如下 所示: public c