文档章节

Android 事件分发 简单学

拉风的道长
 拉风的道长
发布于 2018/08/15 11:07
字数 869
阅读 16
收藏 0

本文地址:https://my.oschina.net/lifj/blog/1928132

Android 事件分发过程

网上有很多这样的文章,我又写了一篇,希望能够清晰明了的告诉大家整体的事件分发过程,而不是一脸懵逼的进来,一脸懵逼的出去。

三个事件

  • dispatchTouchEvent (View 和 ViewGroup都有)
  • onInterceptTouchEvent(只有ViewGroup有
  • onTouchEvent(View 和 ViewGroup都有)

事件的调用流程图

从上图可以看到:dispatchTouchEvent的返回值可能是由两部分决定的:自身的touchEvent返回值,或者子view的dispatchTouchEvent的返回值。

整体分发思路 -- 伪代码

/*
 * 事件分发的伪代码
 */
public class Layout extends ViewGroup{
    private View targetChild = null;//记录DOWN事件找到的目标view,作为后续事件的分发对象。
    public boolean dispatchTouchEvent(MotionEvent event){

        if(this instanceof ViewGroup){
            //DOWN的时候targetChild为null。其他后续事件不为null。
            if(targetChild != null){
                //MOVE,UP,CANCEL等事件直接dispatch过去。
                return targetChild.dispatchTouchEvent(event);
            }

            //DOWN的时候会走以下逻辑
            boolean interceptRet = this.onInterceptTouchEvent(event);
            if(interceptRet == true){
                //拦截,调用自身的onTouchEvent,并返回
               return this.onTouchEvent(event);
            }else if(interceptRet == false){
                //不拦截,遍历子View
                for(int i = 0 ;i< getChildCount();i++){
                    targetChild = getChildAt(i); //判断是不是目标View
                    if(targetChild.dispatchTouchEvent(event)){
                        //dispatchTouchEvent返回true,说明是。并返回
                        return true;
                    }else{
                        //否则不是
                        targetChild = null;
                    }
                }
                //没有找到targetView,调用自身的TouchEvent,并返回
                if(targetChild == null){
                    return this.onTouchEvent(event);
                }
            }
        }else if(this instanceof View){
            //View直接走自己的onTouchEvent
            return this.onTouchEvent(event);
        }

        return false;
    }

}

各自的作用

dispatchTouchEvent: 对于ViewGroup来说:根据onInterceptTouchEvent的返回值,决定调用自身的onTouchEvent还是分发到子view里面。 对于View来说:直接调用onTouchEvent。

onInterceptTouchEvent: 告诉dispatchTouchEvent是不是需要分发下去(也就是被拦截)

onTouchEvent: 自身的处理

Down 与其他事件

Down事件的特殊之处

Down事件作为Event的第一个事件,担任的重任就是找到需要处理Event的控件。如果Down分发一遍之后没有找到需要处理事件,那么这个消息就不会再传到这些View(ViewGroup)中了。 怎么知道没有控件去处理呢?就是通过dispatchTouchEvent的返回值判断的: 返回false,说明没有view需要处理事件。 返回true,说明有View需要处理。对于View,就是自己需要处理。对于ViewGroup,可能是子View需要处理,也可能是自己需要处理。

当返回true之后,ViewGroup中会记录需要处理的View的对象,作为targetChild。否则的话targetChild为null。

其他事件

根据Down事件的返回结果,返回false的话,后续其他的事件都不会分发下来。

返回true的情况,第一个调用的还是dispatchTouchEvent,上一次Down事件记录了targetChild,那么就会直接调用targetChild的dispatchTouchEvent。如此调用下去,直到return true。

事件的来源

android.os.Looper.loop(Looper.java:136) 取出消息
InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6188)
android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3859)
android.view.View.dispatchPointerEvent(View.java:10244)
android.app.Activity.dispatchTouchEvent(Activity.java:3065)
com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1808)
com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:416)
android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2264)

也就是说:事件会被放到Activity的Looper中。 然后从Looper中取出,传给ViewRootImpl,入队。 ViewRootImpl中的deliver去传递事件给View,给Activity,给DocerView. (启动Activity会创建ViewRootImpl和PhoneWindow,建立起与WMS(window manager service)的连接)

© 著作权归作者所有

共有 人打赏支持
拉风的道长
粉丝 54
博文 110
码字总数 55629
作品 0
昌平
程序员
私信 提问
Android 机制篇 - 事件分发机制超详解(🔥🔥🔥🔥🔥🔥🔥🔥)

Android 虽然不是四大组件,但其并不比四大组件的地位低(涉及面的广度和深入甚至比四大组件还复杂🔥)。而View的核心知识点“事件分发机制”则是不少刚入门同学的拦路虎(1、项目中处处遇...

Pepsimaxin
2018/07/12
0
0
安卓自定义View进阶-事件分发机制原理

安卓自定义View进阶-事件分发机制原理 之前讲解了很多与View绘图相关的知识,你可以在 安卓自定义View教程目录 中查看到这些文章,如果你理解了这些文章,那么至少2D绘图部分不是难题了,大部...

猴亮屏
2018/05/22
0
0
Android 官方架构组件(一)——Lifecycle

什么是Lifecycle? Lifecycle 组件指的是 android.arch.lifecycle 包下提供的各种类与接口,可以让开发者构建能感知其他组件(主要指Activity 、Fragment)生命周期(lifecycle-aware)的类。...

Android小安
01/17
0
0
Android-Lifecycle超能解析-生命周期的那些事儿

版权声明:本文已授权微信公众号:Android必修课,转载请申明出处 众所周知,Android凡是需要展示给用户看的,都包含着生命周期这个概念,例如Activity、Fragment、View等都与生命周期息息相...

亭子happy
03/05
0
0
Android Touch事件传递机制解析

没事逛论坛,无意间看到了一篇非常不错的帖子,转载如下: 开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把android touch机制好好看了一下,呵呵。。 an...

长平狐
2012/10/09
2.1K
0

没有更多内容

加载失败,请刷新页面

加载更多

activiti6+springboot连接mysql

application.properties spring.datasource.url=jdbc:mysql://130.51.23.249:3306/activiti6ui?characterEncoding=utf8&useSSL=truespring.datasource.username=saspring.datasource.passw......

Danni3
21分钟前
1
0
PHP教程中验证正整数is_int($value+0),为什么要这样?

最近学习PHP应用,其中有一段是要验证变量是否为正整数,除了is_numeric($value)外,还要加上is_int($value+0)且($value+0) > 0,为什么还要 +0呢?直接验证$value不行吗? ,只要 is_int($...

dragon_tech
33分钟前
1
0
毕业季,我的Linux求职之路

秋招终于告一段落了,本硕的七年求学之路也快画上了句号。回首求职的这一段日子,痛苦并快乐着。感谢所有陪伴着我走过这一段路程的同学,所有的辛酸都值得铭记。求职的过程中在网上看了很多的...

xiangyunyan
40分钟前
1
0
springMvc异常处理定制化

1、扩展SimpleMappingExceptionResolver来实现springMvc的定制 import org.apache.commons.codec.binary.Base64;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.......

重城重楼
今天
4
0
OSChina 周四乱弹 —— Im fine

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @LuckyXu:分享戴荃的单曲《小荃拳之歌》: 手机党少年们想听歌,请使劲儿戳(这里) 今天遇到倒霉事了, @ FalconChen :电梯宕机了我靠 但是...

小小编辑
今天
884
19

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部