Android事件分发机制详解

事件分发机制详解

一、基础知识介绍

1、经常用的事件有:MotionEvent.ACTION_DOWN,MotionEvent.ACTION_MOVE,MotionEvent.ACTION_UP等

2、常用的方法有:disPatchTouchEvent(),onTouchEvent(),onInterceptTouchEvent()(只有ViewGroup才有这个方法,View没有这个方法,且ViewGroup是View的子类);

二、方法功能介绍

1、dispatchTouchEvent事件分发的调度者与指挥者,触发的第一个方法

2、onInterceptTouchEvent,决定是否拦截事件:

3、如果拦截事件,调用当前控件的onTouchEvent方法,

4、如果不拦截,判断是否有子控件,

5、onTouchEvent,决定是否消费事件,消费返回True,不消费返回False。如果返回的为false,之后的事件都不会再传递到当前的控件了(会不再访问当前控件),如果返回true,之后的事件依然还是会传递过来的。

三、各个方法和控件之间事件传递关系

事件传递流程:事件—>Activity—>Window—>DecorView—>ViewTree(嵌套在一起的各种控件)

一个事件,首先会由Activity的dispatchTouchEvent方法接受,然后分发到附着在Activity上的Window,Window不进行处理直接分发到ViewTree;最外层的ViewTop(默认为是ViewGroup类型的)会先调用自己的dispatchTouchEvent方法,然后由dispatchTouchEvent调用onInterceptTouchEvent方法,如果返回true,调用自己的onTouchEvent方法;如果返回false,继续向下一个控件进行事件分发。

如果ViewTree中的所有控件都不消费,那就返回到Activity中,由Activity调用onTouchEvent方法。

下面给大家一个具体的例子,大家可以有一个形象的感受。

四、示例Demo(示例中的代码是不考虑下面说的特殊情况的)

布局文件

<VP1>

<VP2>

<CustomView/>

</VP2>

</VP1>

1、控件都不消费

down事件

Log:-Activity:dispatchTouchEvent:调用

Log:-VP1:dispatchTouchEvent:调用

Log:-VP1:onInterceptTouchEvent:调用

Log:-VP1:onInterceptTouchEvent:返回:false

Log:-VP2:dispatchTouchEvent:调用

Log:-VP2:onInterceptTouchEvent:调用

Log:-VP2:onInterceptTouchEvent:返回:false

Log:-CustomView:dispatchTouchEvent:调用

Log:-CustomView:touchEvent:调用

Log:-CustomView:touchEvent:返回:false

Log:-CustomView:dispatchTouchEvent:返回:false

Log:-VP2:touchEvent:调用

Log:-VP2:touchEvent:返回:false

Log:-VP2:dispatchTouchEvent:返回:false

Log:-VP1:touchEvent:调用

Log:-VP1:touchEvent:返回:false

Log:-VP1:dispatchTouchEvent:返回:false

Log:-Activity:touchEvent:调用

Log:-Activity:touchEvent:返回:false

Log:-Activity:dispatchTouchEvent:返回:false

up事件

Log:-Activity:dispatchTouchEvent:调用

Log:-Activity:touchEvent:调用

Log:-Activity:touchEvent:返回:false

Log:-Activity:dispatchTouchEvent:返回:false

2、CustomView消费

down事件

Log:-Activity:dispatchTouchEvent:调用

Log:-VP1:dispatchTouchEvent:调用

Log:-VP1:onInterceptTouchEvent:调用

Log:-VP1:onInterceptTouchEvent:返回:false

Log:-VP2:dispatchTouchEvent:调用

Log:-VP2:onInterceptTouchEvent:调用

Log:-VP2:onInterceptTouchEvent:返回:false

Log:-CustomView:dispatchTouchEvent:调用

Log:-CustomView:touchEvent:调用

Log:-CustomView:touchEvent:返回:true

Log:-CustomView:dispatchTouchEvent:返回:true

Log:-VP2:dispatchTouchEvent:返回:true

Log:-VP1:dispatchTouchEvent:返回:true

Log:-Activity:dispatchTouchEvent:返回:true

Up事件

Log:-Activity:dispatchTouchEvent:调用

Log:-VP1:dispatchTouchEvent:调用

Log:-VP1:onInterceptTouchEvent:调用

Log:-VP1:onInterceptTouchEvent:返回:false

Log:-VP2:dispatchTouchEvent:调用

Log:-VP2:onInterceptTouchEvent:调用

Log:-VP2:onInterceptTouchEvent:返回:false

Log:-CustomView:dispatchTouchEvent:调用

Log:-CustomView:touchEvent:调用

Log:-CustomView:touchEvent:返回:true

Log:-CustomView:dispatchTouchEvent:返回:true

Log:-VP2:dispatchTouchEvent:返回:true

Log:-VP1:dispatchTouchEvent:返回:true

Log:-Activity:dispatchTouchEvent:返回:true

3、VP2拦截不消费

Down事件

Log:-Activity:dispatchTouchEvent:调用

Log:-VP1:dispatchTouchEvent:调用

Log:-VP1:onInterceptTouchEvent:调用

Log:-VP1:onInterceptTouchEvent:返回:false

Log:-VP2:dispatchTouchEvent:调用

Log:-VP2:onInterceptTouchEvent:调用

Log:-VP2:onInterceptTouchEvent:返回:true

Log:-VP2:touchEvent:调用

Log:-VP2:touchEvent:返回:false

Log:-VP2:dispatchTouchEvent:返回:false

Log:-VP1:touchEvent:调用

Log:-VP1:touchEvent:返回:false

Log:-VP1:dispatchTouchEvent:返回:false

Log:-Activity:touchEvent:调用

Log:-Activity:touchEvent:返回:false

Log:-Activity:dispatchTouchEvent:返回:false

UP事件

Log:-Activity:dispatchTouchEvent:调用

Log:-Activity:touchEvent:调用

Log:-Activity:touchEvent:返回:false

Log:-Activity:dispatchTouchEvent:返回:false

4、VP2拦截消费

Down事件

Log:-Activity:dispatchTouchEvent:调用

Log:-VP1:dispatchTouchEvent:调用

Log:-VP1:onInterceptTouchEvent:调用

Log:-VP1:onInterceptTouchEvent:返回:false

Log:-VP2:dispatchTouchEvent:调用

Log:-VP2:onInterceptTouchEvent:调用

Log:-VP2:onInterceptTouchEvent:返回:true

Log:-VP2:touchEvent:调用

Log:-VP2:touchEvent:返回:true

Log:-VP2:dispatchTouchEvent:返回:true

Log:-VP1:dispatchTouchEvent:返回:true

Log:-Activity:dispatchTouchEvent:返回:true

UP事件

Log:-Activity:dispatchTouchEvent:调用

Log:-VP1:dispatchTouchEvent:调用

Log:-VP1:onInterceptTouchEvent:调用

Log:-VP1:onInterceptTouchEvent:返回:false

Log:-VP2:dispatchTouchEvent:调用

Log:-VP2:touchEvent:调用

Log:-VP2:touchEvent:返回:true

Log:-VP2:dispatchTouchEvent:返回:true

Log:-VP1:dispatchTouchEvent:返回:true

Log:-Activity:dispatchTouchEvent:返回:true

五、特殊情况

1、如果disallowIntercept=true,那么不会再走控件中的onInterceptTouchEvent方法,直接标记为不拦截事件。

2、如果有requestDisallowInterceptTouchEvent(true)方法,父类控件不走onInterceptTouchEvent方法,不用通过回调来判断是否需要拦截事件,而是直接进行传送。

3、这两方面,主要是用来解决手势冲突的。

六、小提示

1、如果满足下列条件之一,就会调用onTouchEvent方法。

  1. 所处的view拦截了事件
  2. 没有子View
  3. 子View都不消费事件

2、onTouchListener中的onTouch回调与dispatchTouchEvent的优先级一样,都是优先于onTouchEvent的

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏懒人开发

dispatchTouchEvent事件分发浅析(五)消费

上一篇,我们大体理解了Intercept拦截 而之前 也了解了 分发的过程, 和简单点击,分析了执行顺序

1285
来自专栏Android Note

Android-录屏APP该怎么实现?

1312
来自专栏中国Android研究院

进阶必备-Android事件分发机制

或许你会问,“为什么我一定要知道View的事件分发机制?”。因为我们在实际开发的过程中,经常会遇到多层的View互相嵌套以后,对某一个View进行滑动的时候,特...

1164
来自专栏向治洪

android viewgroup事件分发机制

今天给大家代码ViewGroup事件分发的源码解析~~凡是自定义ViewGroup实现各种滑动效果的,不可避免的会出现很多事件的冲突,对ViewGroup事件分...

2016
来自专栏开发之途

Android 解决 View 的滑动冲突

关于 Android 的 TouchEvent 事件分发机制可以看这里:Java_Android_Learn,本文讲解的是如何去解决 View 之间的滑动冲突

1031
来自专栏每日一篇技术文章

VR+全景播放器+头控讲解-06

在UIView上面布局我们可以使用UIButton UIView UIImageView等,但是是在3D场景中,我们不能使用UIView,我们要使用平面几何当视...

801
来自专栏曾大稳的博客

Android View的Touch事件分发

事件分发的重要性我就不多说了,我们先从简到难。 先看View的Touch事件分发,我自定义一个View,重写OnTouchEvent函数,然后分别设置OnTou...

1772
来自专栏何俊林

Android仿京东、天猫app的商品详情页的布局架构, 以及功能实现

前言:电商内app,重点在于详情页商品展示,用户不仅要看到图,可以看到各种描述,以及相关规格参数。今天是coexist独家授权本公众号独家发布的《仿京东、天猫a...

30610
来自专栏移动开发面面观

Android事件分发备忘

1163
来自专栏开发之途

Android TouchEvent事件分发机制详解(1)

1545

扫码关注云+社区

领取腾讯云代金券