android的事件分发测试结果

简单版,没有精力完善更多的东西。

测试对象:

EventActivity:重写了dispatchTouchEvent和onTouchEvent

EventViewGroup1:重写了dispatchTouchEvent和onInterceptTouchEvent和onTouchEvent

EventViewGroup2:重写了dispatchTouchEvent和onInterceptTouchEvent和onTouchEvent

EventView:重写了dispatchTouchEvent和onTouchEvent

测试情况一:dispatchTouchEvent和onInterceptTouchEvent和onTouchEvent三个被重写的方法都返回super.xxx

输出结果为:

06-15 08:14:56.962    1695-1695/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 08:14:56.962    1695-1695/com.aprz.delak E/EventTest﹕ EventViewGroup1---dispatchTouchEvent---

06-15 08:14:56.962    1695-1695/com.aprz.delak E/EventTest﹕ EventViewGroup1---onInterceptTouchEvent---

06-15 08:14:56.962    1695-1695/com.aprz.delak E/EventTest﹕ EventViewGroup2---dispatchTouchEvent---

06-15 08:14:56.962    1695-1695/com.aprz.delak E/EventTest﹕ EventViewGroup2---onInterceptTouchEvent---

06-15 08:14:56.962    1695-1695/com.aprz.delak E/EventTest﹕ EventView---dispatchTouchEvent---

06-15 08:14:56.963    1695-1695/com.aprz.delak E/EventTest﹕ EventView---onTouchEvent---

06-15 08:14:56.963    1695-1695/com.aprz.delak E/EventTest﹕ EventViewGroup2---onTouchEvent---

06-15 08:14:56.963    1695-1695/com.aprz.delak E/EventTest﹕ EventViewGroup1---onTouchEvent---

06-15 08:14:56.963    1695-1695/com.aprz.delak E/EventTest﹕ EventActivity---onTouchEvent---

06-15 08:14:57.070    1695-1695/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 08:14:57.070    1695-1695/com.aprz.delak E/EventTest﹕ EventActivity---onTouchEvent---

06-15 08:14:57.086    1695-1695/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 08:14:57.086    1695-1695/com.aprz.delak E/EventTest﹕ EventActivity---onTouchEvent---

06-15 08:14:57.103    1695-1695/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 08:14:57.103    1695-1695/com.aprz.delak E/EventTest﹕ EventActivity---onTouchEvent---

最后只打印EventActicity是因为:EventViewGroup1和EventViewGroup2和EventViewGroup1都不消费事件,所以本次的后续事件就不往下传递了,activity自己处理。

为了证明上面的结论,做这样一个测试,让EventViewGroup2来消费这次事件(在onTouchEvent里返回true),输出打印结果如下:

06-15 08:16:52.590    1800-1800/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 08:16:52.590    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup1---dispatchTouchEvent---

06-15 08:16:52.590    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup1---onInterceptTouchEvent---

06-15 08:16:52.590    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup2---dispatchTouchEvent---

06-15 08:16:52.590    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup2---onInterceptTouchEvent---

06-15 08:16:52.590    1800-1800/com.aprz.delak E/EventTest﹕ EventView---dispatchTouchEvent---

06-15 08:16:52.590    1800-1800/com.aprz.delak E/EventTest﹕ EventView---onTouchEvent---

06-15 08:16:52.590    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup2---onTouchEvent---

06-15 08:16:52.703    1800-1800/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 08:16:52.703    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup1---dispatchTouchEvent---

06-15 08:16:52.703    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup1---onInterceptTouchEvent---

06-15 08:16:52.703    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup2---dispatchTouchEvent---

06-15 08:16:52.703    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup2---onTouchEvent---

06-15 08:16:52.720    1800-1800/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 08:16:52.720    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup1---dispatchTouchEvent---

06-15 08:16:52.721    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup1---onInterceptTouchEvent---

06-15 08:16:52.721    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup2---dispatchTouchEvent---

06-15 08:16:52.721    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup2---onTouchEvent---

06-15 08:16:52.736    1800-1800/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 08:16:52.736    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup1---dispatchTouchEvent---

06-15 08:16:52.736    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup1---onInterceptTouchEvent---

06-15 08:16:52.736    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup2---dispatchTouchEvent---

06-15 08:16:52.736    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup2---onTouchEvent---

06-15 08:16:52.753    1800-1800/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 08:16:52.753    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup1---dispatchTouchEvent---

06-15 08:16:52.753    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup1---onInterceptTouchEvent---

06-15 08:16:52.753    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup2---dispatchTouchEvent---

06-15 08:16:52.753    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup2---onTouchEvent---

06-15 08:16:52.770    1800-1800/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 08:16:52.770    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup1---dispatchTouchEvent---

06-15 08:16:52.770    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup1---onInterceptTouchEvent---

06-15 08:16:52.770    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup2---dispatchTouchEvent---

06-15 08:16:52.770    1800-1800/com.aprz.delak E/EventTest﹕ EventViewGroup2---onTouchEvent---

可以看出后续的事件,每次传递到EventViewGroup2便不往下面传递了,这也正说明了:

dispatchTouchEvent()方法中有“记忆”的功能,如果第一次事件向下传递到某View,它把事件继续传递交给它的子View,它会记录该事件是否被它下面的View给处理成功了,(怎么能知道呢?如果该事件会再次被向上传递到我这里来由我的onTouchEvent()来处理,那就说明下面的View都没能成功处理该事件);当第二次事件向下传递到该View,该View的dispatchTouchEvent()方法机会判断,若上次的事件由下面的view成功处理了,那么这次的事件就继续交给下面的来处理,若上次的事件没有被下面的处理成功,那么这次的事件就不会向下传递了,该View直接调用自己的onTouchEvent()方法来处理该事件。

“记忆”功能的信息只在一系列事件完成之前有效,如从ACTION_DOWN事件开始,直到后续事件ACTION_MOVE,ACTION_UP结束后,“记忆”的信息就会清除。也就是说如果某View处理ACTION_DOWN事件失败了(onTouchEvent()返回false),那么后续的ACTION_MOVE,ACTION_UP等事件就不会再传递到该View了,由其父View自己来处理。在下一次发生ACTION_DOWN事件的时候,还是会传递到该View的。

测试情况二:看看EventViewGroup1的dispatchTouchEvent返回返回true,会发生什么?

06-15 07:11:02.797    2154-2154/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 07:11:02.797    2154-2154/com.aprz.delak E/EventTest﹕ EventViewGroup1---dispatchTouchEvent---

06-15 07:11:02.938    2154-2154/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 07:11:02.938    2154-2154/com.aprz.delak E/EventTest﹕ EventViewGroup1---dispatchTouchEvent---

06-15 07:11:02.952    2154-2154/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 07:11:02.952    2154-2154/com.aprz.delak E/EventTest﹕ EventViewGroup1---dispatchTouchEvent---

06-15 07:11:02.968    2154-2154/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 07:11:02.969    2154-2154/com.aprz.delak E/EventTest﹕ EventViewGroup1---dispatchTouchEvent---

06-15 07:11:02.984    2154-2154/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 07:11:02.985    2154-2154/com.aprz.delak E/EventTest﹕ EventViewGroup1---dispatchTouchEvent---

可以看出,事件被EventViewGroup1的dispatchTouchEvent消费了。

测试情况三:看看EventViewGroup1的dispatchTouchEvent返回返回false,会发生什么?

06-15 07:16:51.100    2358-2358/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 07:16:51.100    2358-2358/com.aprz.delak E/EventTest﹕ EventViewGroup1---dispatchTouchEvent---

06-15 07:16:51.100    2358-2358/com.aprz.delak E/EventTest﹕ EventActivity---onTouchEvent---

06-15 07:16:51.168    2358-2358/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 07:16:51.168    2358-2358/com.aprz.delak E/EventTest﹕ EventActivity---onTouchEvent---

06-15 07:16:51.184    2358-2358/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 07:16:51.184    2358-2358/com.aprz.delak E/EventTest﹕ EventActivity---onTouchEvent---

06-15 07:16:51.201    2358-2358/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 07:16:51.201    2358-2358/com.aprz.delak E/EventTest﹕ EventActivity---onTouchEvent---

事件被返回给上层来源了,让其onTouchEvent来处理。

测试情况四:看看EventViewGroup2的dispatchTouchEvent返回返回false,会发生什么?

06-15 07:20:03.892    2463-2463/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 07:20:03.892    2463-2463/com.aprz.delak E/EventTest﹕ EventViewGroup1---dispatchTouchEvent---

06-15 07:20:03.892    2463-2463/com.aprz.delak E/EventTest﹕ EventViewGroup1---onInterceptTouchEvent---

06-15 07:20:03.892    2463-2463/com.aprz.delak E/EventTest﹕ EventViewGroup2---dispatchTouchEvent---

06-15 07:20:03.892    2463-2463/com.aprz.delak E/EventTest﹕ EventViewGroup1---onTouchEvent---

06-15 07:20:03.892    2463-2463/com.aprz.delak E/EventTest﹕ EventActivity---onTouchEvent---

06-15 07:20:04.002    2463-2463/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 07:20:04.002    2463-2463/com.aprz.delak E/EventTest﹕ EventActivity---onTouchEvent---

06-15 07:20:04.018    2463-2463/com.aprz.delak E/EventTest﹕ EventActivity---dispatchTouchEvent---

06-15 07:20:04.019    2463-2463/com.aprz.delak E/EventTest﹕ EventActivity---onTouchEvent---

事件返回给上层去处理了,如果上层也不处理,继续向上返回,一直到activity,可以看出activity和ViewGroup是不一样的,就算不处理事件,仍然会接收到下次事件。

最终的结论如下:

? 事件分发: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,事件分发分为两种情况:
    1.   如果当前 View 获取的事件直接来自 Activity,则会将事件返回给 Activity 的 onTouchEvent 进行消费;
    2.   如果当前 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),与返回false时相同。

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

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

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

android的事件分发测试结果的相关文章

Android View 事件分发机制 源码解析 (上)

一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~ 首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个MyButton继承Button,然后把跟事件传播有关的方法进行复写,然后添加上日志~ MyButton [java] view plain copy package com.example.zhy_event03; import android.content.Context; import andr

从源码角度带你分析 Android View 事件分发 dispatchTouchEvent,onTouch,onTouchEvent,onClick逻辑顺序过程(一)

关于Android View 事件分发过程的文章网络上可以搜到一把大,这里贴一篇代码性的文章,作者也是个牛人:Android事件分发机制完全解析,带你从源码的角度彻底理解(上). 虽然讲的很好,但是看完之后还是感觉有那么点一知半解,于是自己花了点时间从源码研究android 触摸事件分发流程,以下内容仅仅个人理解,如有差错希望指出. 我们先从一个例子看起,先重写一个MyButton 继承Button,代码如下: public class MyButton extends Button { pub

Android Touch事件分发过程

虽然网络上已经有非常多关于这个话题的优秀文章了,但还是写了这篇文章,主要还是为了加强自己的记忆吧,自己过一遍总比看别人的分析要深刻得多.那就走起吧. 简单演示样例 先看一个演示样例 : 布局文件 : <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id=&q

Android触摸事件分发

Android的触摸分发机制和如何实现拦截 Android的触摸分发机制和如何实现拦截 前言 触摸事件的分发 情景分析 总结 前言 在自定义ViewGroup中,有时候需要实现触摸事件拦截,比如ListView下拉刷新就是典型的触摸事件拦截的例子.触摸事件拦截就是在触摸事件被parent view拦截,而不会分发给其child,即使触摸发生在该child身上.被拦截的事件会转到parent view的onTouchEvent方法中进行处理.但是这个交互过程还是挺复杂的,有多种情况,今天我们就来分

Android View 事件分发机制源码详解(View篇)

前言 在Android View 事件分发机制源码详解(ViewGroup篇)一文中,主要对ViewGroup#dispatchTouchEvent的源码做了相应的解析,其中说到在ViewGroup把事件传递给子View的时候,会调用子View的dispatchTouchEvent,这时分两种情况,如果子View也是一个ViewGroup那么再执行同样的流程继续把事件分发下去,即调用ViewGroup#dispatchTouchEvent:如果子View只是单纯的一个View,那么调用的是Vie

Android Touch事件分发详解

Android Touch事件分发详解 先说一些基本的知识,方便后面分析源码时能更好理解. - 所有Touch事件都被封装成MotionEvent对象,包括Touch的位置.历史记录.第几个手指等. 事件类型分为ACTION_DOWN,ACTION_UP,ACTION_MOVE,ACTION_POINTER_DOWN,ACTION_POINTER_UP,ACTION_CANCEL, 每个 一个完整的事件以ACTION_DOWN开始ACTION_UP结束,并且ACTION_CANCEL只能由代码引

Android View事件分发机制

最近在开发中遇到view滑动冲突的问题,由于一开始就知道这个问题与view事件分发有关,之后在网上看了几篇关于事件分发的资料后,开发中遇到的问题很快便得到解决. 在这里总结一下我对view事件分发的理解. 首先,看下事件分发流程图: Button事件演示 在对view的事件分发机制进行分析前,我们可以通过一个demo看看Button的事件处理的流程. 在布局文件中添加一个button控件,然后在代码中实现Button的setOnClickListener和setOnTouchListener方法

Android View 事件分发机制梳理

View初探 一直以来对View的事件分发机制很晕,今天就在这里梳理一下 MyView 首先继承View类,自定义一个MyView.并在初始化时打印View类是否可点击,这里从View点击事件分发的角度出发,所以不考虑绘制,测量相关方法的实现. public class MyView extends View { String TAG = "Activity"; public MyView(Context context) { super(context); init(); } pub

谈谈我对Android View事件分发的理解

写这篇博客的缘由.近期因为项目中用到相似一个LinearLayout中水平布局中,有一个TextView和Button,然后对该LinearLayout布局设置点击事件.点击TextView能够触发该点击事件.然而奇怪的是点击Button却不能触发. 然后google到了解决的方法(重写Button,然后重写当中的ontouchEvent方法,且返回值为false).可是不知道原因,这两天看了几位大神的博客,然后自己总结下. public class MyButton extends Butto