博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 事件分发 简单学
阅读量:6573 次
发布时间:2019-06-24

本文共 3308 字,大约阅读时间需要 11 分钟。

  hot3.png

本文地址:

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)的连接)

转载于:https://my.oschina.net/lifj/blog/1928132

你可能感兴趣的文章
etcd 集群的管理 - 暴走漫画容器实践系列 Part4
查看>>
Emmet不完全总结
查看>>
Fragment初学3——使用Fragment的子类DialogFragment
查看>>
安波福与博世各出奇招,CES 热身赛已经开打
查看>>
阿里发布商业操作系统背后:云技术推动商业变革
查看>>
PostgreSQL 10.1 手册_部分 II. SQL 语言_第 8 章 数据类型_8.8. 几何类型
查看>>
软件测试面试题集合(一)
查看>>
js前端转换Date或秒数的时间格式
查看>>
Android View 及 Input 类之间关系
查看>>
Mac OS上反编译android app的环境搭建
查看>>
vuex 在非组件中调用 actions 方法
查看>>
Android之路 - 冷启动解决方案:实现秒开
查看>>
mysql语法
查看>>
区块链开发公司谈区块链影响着哪些行业
查看>>
tomcat session 共享 redis
查看>>
discuz 搭建(前提lnmp环境)
查看>>
ActiveMQ专题1: 入门实例
查看>>
设计模式(二)_ 策略模式
查看>>
像学R一样学Python数据分析之基本数据管理
查看>>
shell脚本编程
查看>>