event android,androidEvent 对 android 事件分发机制的一点个人理解,将事件机制进行了简单化处理,刚方便理解! @codeKK Android开源站...

android 中的事件处理一直以来困扰不少刚刚从事 android 开发的同学,网上也有不少讲解 android 事件分发的文章,然而讲解的都不够简洁!现在我将用另一种简洁的方式来讲解 android 事件的分发机制!

android 的事件分发可以简单的归位两类:1.view 的事件分发和处理 2.ViewGroup 的事件分发和处理。我们首先分析 View 的事件分发和处理。

View 的事件分发和处理

View 中的事件分发和处理涉及到了两个方法:

1.public boolean dispatchTouchEvent(MotionEvent event) 2.public boolean onTouchEvent(MotionEvent event) 它们的返回值都为 boolean 类型。

在 View 中 dispatchTouchEvent(MotionEvent event) 负责将事件分发给 onTouchEvent(MotionEvent event)来处理,简单一点理解就是下面的这段代码

@Override

public boolean dispatchTouchEvent(MotionEvent event) {

Log.i("eventTest", "=EventView======dispatchTouchEvent==" + event.getAction());

boolean handed = onTouchEvent(event);

return handed;

}

@Override

public boolean onTouchEvent(MotionEvent event) {

Log.i("eventTest", "=EventView======onTouchEvent==" + event.getAction());

return true;

}

通过简易模型我们可以看到:

在 dispatchTouchEvent(MotionEvent event)只要返回 true 就代表这个 View 消耗了这个事件。

如果在 onTouchEvent(MotionEvent event)中返回 true

那么这个事件的传递链就是这样的:activity 的 dispatchTouchEvent()——>ViewGroup 的 dispatchTouchEvent()——>ViewGroup onInterceptTouchEvent()——>view 的 dispatchTouchEvent()

——> view 的 onTouchEvent();

如果在 dispatchTouchEvent(MotionEvent event)中直接返回 true。类似于这样

public boolean dispatchTouchEvent(MotionEvent event) {

Log.i("eventTest", "=EventView======dispatchTouchEvent==" + event.getAction());

return true;

}

那么这个事件依旧是被这个 View 消耗了是被 dispatchTouchEvent()消耗的,并没有将事件分发给 onTouchEvent(),所以这个 View 的 onTouchEvent()不会执行,这是这个事件的传递链是这样的:activity 的 dispatchTouchEvent()——>ViewGroup 的 dispatchTouchEvent()——>ViewGroup onInterceptTouchEvent(——>view 的 dispatchTouchEvent()。

在 dispatchTouchEvent(MotionEvent event)只要返回 false 就代表这个 View 不消耗这个事件。

如果在 onTouchEvent(MotionEvent event)中返回 false,除了 action_down 以外后续事件都不会传递到这个 View 上

当然如果直接在 dispatchTouchEvent(MotionEvent event)中直接返回 false,这个 View 的 onTouchEvent()不会执行。原理同直接返回 true;

然而在现实中经常会看见这样的写法:

@Override

public boolean dispatchTouchEvent(MotionEvent event) {

Log.i("eventTest", "=EventView======dispatchTouchEvent==" + event.getAction());

return super.dispatchTouchEvent(event);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

Log.i("eventTest", "=EventView======onTouchEvent==" + event.getAction());

return super.onTouchEvent(event);

}

它们调用 super 的方法是因为在父类中它们各自定义了一些事件分发或者事件处理逻辑。特别是在 super.dispatchTouchEvent 中定义了将事件交给

onTouchEvent()处理的逻辑。

ViewGroup 的事件分发和处理

ViewGroup 中的事件分发出处理涉及到了三个方法:

1.public boolean dispatchTouchEvent(MotionEvent event) 2.public boolean onInterceptTouchEvent(MotionEvent ev) 3.public boolean onTouchEvent(MotionEvent event) 它们的返回值都是 boolean 类型。

在 ViewGroup 中 dispatchTouchEvent(MotionEvent event) 负责先将事件分发给自己 onInterceptTouchEvent(MotionEvent ev)

来判断自己是否拦截事件,如果 onInterceptTouchEvent(MotionEvent ev) 返回 true,表示自己要拦截这个事件,那么这个事件就会交给自己的

onTouchEvent(MotionEvent event)处理,如果事件被自己的 onTouchEvent()消耗,那么后续事件将直接交给自己的 onTouchEvent()处理,如果事件不消耗,那么 ViewGroup 的父控件不会再将事件分发过来。如果不拦截事件那么 ViewGroup 就会将事件分发给子 View,如果子 View 也不处理这个事件,那么它就会将事件交给自己的 onTouchEvent(MotionEvent event)来处理。简单一点理解就是下面的这段代码

@Override

public boolean dispatchTouchEvent(MotionEvent ev) {

Log.i("eventTest", "=EventViewGroup======dispatchTouchEvent==" + ev.getAction());

if (!inter) {

inter = onInterceptTouchEvent(ev);

}

if (inter) {

handed = onTouchEvent(ev);

} else {

childHanded = getChildAt(0).dispatchTouchEvent(ev);

if (!childHanded) {

handed = onTouchEvent(ev);

}

}

return handed || childHanded;

}

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

Log.i("eventTest", "=EventViewGroup======onInterceptTouchEvent==" + ev.getAction());

return false;

}

@Override

public boolean onTouchEvent(MotionEvent event) {

Log.i("eventTest", "=EventViewGroup======onTouchEvent==" + event.getAction());

return false;

}

通过简易模型我们可以看到:

ViewGroup 的 onInterceptTouchEvent()则是用来直接拦截事件的,如果返回 true,就代表本 ViewGroup 要拦截事件并将事件交给自己的 onTouchEvent 处理。事件一旦被拦截 就不会再分发给当前 ViewGroup 包含的子控件了。

ViewGroup 的 dispatchTouchEvent()返回 true 就代表了这个事件是被这个 ViewGroup 消耗了。而在这个 ViewGroup 中我们知道是 ViewGroup 本身消耗了事件还是它包含的子 view 消耗了事件,从而决定了事件是分发给自己还是包含的子 view。

通过对 ViewGroup 的事件分发模型的简单化,我们可以可以看出来,如果 ViewGroup 的 dispatchTouchEvent(MotionEvent ev)直接返回 true

public boolean dispatchTouchEvent(MotionEvent event) {

Log.i("eventTest", "=EventView======dispatchTouchEvent==" + event.getAction());

return true;

}

那么这个事件就会被当前的 ViewGroup 直接消耗。既不会交给自己的 onInterceptTouchEvent()以及 onTouchEvent(),也不会分发给子 view。

但是如果直接返回 false,当前 viewGroup 既不会消耗事件,也不会对事件做任何分发,但是当前 ViewGroup 会接收到 action_down 事件。

然而在现实中经常会看见这样的写法:

@Override

public boolean dispatchTouchEvent(MotionEvent event) {

Log.i("eventTest", "=EventView======dispatchTouchEvent==" + event.getAction());

return super.dispatchTouchEvent(event);

}

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

Log.i("eventTest", "=EventViewGroup======onInterceptTouchEvent==" + ev.getAction());

return super.dispatchTouchEvent(ev);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

Log.i("eventTest", "=EventView======onTouchEvent==" + event.getAction());

return super.onTouchEvent(event);

}

这是因为父 View 中,对这几个方法都有一些默认的处理逻辑。

activity 的事件分发和处理

activity 的事件分发模型和 ViewGrooup 类似,只是没有 onInterceptTouchEvent(MotionEvent ev)这一步。

可以简单概括为

@Override

public boolean dispatchTouchEvent(MotionEvent ev) {

Log.i("eventTest", "=MainActivity======dispatchTouchEvent==" + ev.getAction());

viewHanded = getWindow().getDecorView().findViewById(android.R.id.content).dispatchTouchEvent(ev);

if (!viewHanded){

handed = onTouchEvent(ev);

}

return handed || viewHanded;

}

@Override

public boolean onTouchEvent(MotionEvent event) {

Log.i("eventTest", "=MainActivity======onTouchEvent==" + event.getAction());

return super.onTouchEvent(event);

}

activity 的事件先传递给它包含的布局来处理,如果布局不处理才会交给自己的 onTouchEvent()处理。

总结

为什么在不拦截不处理事件的情况下,事件的分的过程是有 acttivity.dispatchTouchEvent(MotionEvent ev) -> viewGroup.dispatchTouchEvent(MotionEvent ev) ->onInterceptTouchEvent(MotionEvent ev)-> view.dispatchTouchEvent(MotionEvent ev) -> view.onTouchevent(otionEvent ev)->viewGroup.onTouchevent(otionEvent ev) -> activity.onTouchevent(otionEvent ev)

从对 View 和 viewGroup 以及 activity 中的事件分析我们可以看到事件的分发处理过程是这样的:首先由 activity 优先分发给他的根视图,而根视图会优先判断是否拦截事件,不拦截则对事件做继续分发,直到在某一级视图事件被消耗了才会停止分发这个事件,否则,在最后一层视图,因为它没有子视图了,那么事件的分发就结束了,从而转入对 onTouchevent()的调用,当 onTouchevent()执行结束,它的 dispatchTouchEvent(ev)执行结束即它的父视图的 getChildAt(0).dispatchTouchEvent(ev)执行结束,然后它的父视图就会判断是否调用自己的 onTouchevent()...依次类推,就有了上面的事件分发处理链。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/417096.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

consul docker方式搭建

目录 获取镜像 运行 集群搭建 官网:https://www.consul.io/ 文档:https://www.consul.io/docs/index.html 获取镜像 docker pull consul:1.3.0 运行 如果已存在dev-consul先移除 docker rm -f dev-consul 创建容器,守护进程方式启动&…

锁屏壁纸开发 Android,Android开发自己的锁屏壁纸

SurfaceView SurfaceHolder MediaPlayer Service BroadcastReceiver KeyguardManager PowerManager思路:启动一个服务,监听灭屏广播,当收到广播的时候,点亮屏幕,禁用锁屏,调用使用SurfaceV…

[转载来之雨松:NGUI研究院之为什么打开界面太慢(十三)]

本文固定链接: http://www.xuanyusong.com/archives/2799转载于:https://www.cnblogs.com/yexiaopeng/p/6591482.html

前端学习(2335):angular之内置结构指令ngif

child.html <p>child4 works!</p><div class"us">我是歌谣</div> <div [ngClass]"currentClass" class"col">我是歌谣</div><div *ngIf"true">aaaa</div> <div *ngIf"false…

centos7 postgresql安装

安装 Install the repository RPM: yum install https://download.postgresql.org/pub/repos/yum/11/redhat/rhel-7-x86_64/pgdg-centos11-11-2.noarch.rpm Install the client packages: yum install postgresql11 Optionally install the server packages: yum install …

android密码可见不可见的光标控制,Android EditText 在设置为输入密码的时候 密码是否可见 光标在最后显示...

释放双眼&#xff0c;带上耳机&#xff0c;听听看~&#xff01;今天在开发登录注册模块的时候&#xff0c;用EditText实现密码的输入&#xff0c;项目需要密码是可以选择可见或者默认的隐藏模式&#xff0c;很简单&#xff0c;但是第一次遇到就记录下来分享给大家。布局文件and…

centos6 postgresql安装

安装 Install the repository RPM: yum install https://download.postgresql.org/pub/repos/yum/11/redhat/rhel-6-x86_64/pgdg-centos11-11-2.noarch.rpm Install the client packages: yum install postgresql11 Optionally install the server packages: yum install…

l2-006 树的遍历

L2-006. 树的遍历 时间限制400 ms内存限制65536 kB代码长度限制8000 B判题程序Standard作者陈越给定一棵二叉树的后序遍历和中序遍历&#xff0c;请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。 输入格式&#xff1a; 输入第一行给出一个正整数N&#xff08;&l…

Ant Design Pro 2.0/umijs站点配置到非站点根目录下处理

1.config/config.js中 export default {中加上如下&#xff1a; history: hash, //采用hash路由&#xff1a;#/xxx的形式 base:./, publicPath:./, &#xff08;会自动将/static/xxx.jpg之类的和umi.js中的a.p"/"及index.html中window.routerBase中该值进行替换…

android添加商品到购物车,Android使用动画动态添加商品进购物车

本文实例为大家分享了Android添加商品进购物车的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下1、首先展示下效果图2、讲一下思路&#xff0c;小球由加号位置运动到购物车位置&#xff0c;首先得获得这两个点在整个屏幕中的坐标&#xff0c;然后分别计算这两个点的横…

字体小于12px解决办法

width: 100px; height: 30px;-webkit-transform: scale(0.5);margin: -7.5px -25px; 转载于:https://www.cnblogs.com/yghgo/p/6593449.html

前端学习(2338):记录解决问题的一次

<!DOCTYPE html> <html><head><meta charset"utf-8" /><title></title><style type"text/css">#f {font-size: 50px;font-family: 幼圆;}#btn {width: 50px;height: 30px;opacity: 0.5;background-color: paleg…

URAL1553 Caves and Tunnels 树链剖分 动态树

URAL1553 维护一棵树&#xff0c;随时修改某个节点的权值&#xff0c;询问&#xff08;x,y&#xff09;路径上权值最大的点。 树是静态的&#xff0c;不过套动态树也能过&#xff0c;时限卡的严就得上树链剖分了。 还是那句话 splay的核心是splay(x) LCT的核心是access(x) 把SP…

zb——中国人发起的编程语言之序章

20181110 大背景 贸易战&#xff0c;java11收费&#xff0c;python go等百家争鸣&#xff0c;但是没有一个是中国人发起创立的语言。 思考 夜来奇想&#xff0c;java不行了还有go&#xff0c;go如果要是不行了呢&#xff1f;python等都不行了呢&#xff1f; 中国人自己发起…

华为5g鸿蒙折叠,华为再次亮剑!5G新旗舰已经确认,折叠屏+升级到鸿蒙2.0,价格过万...

每年华为有两个新机上市高峰期&#xff0c;一个是年初的P系列发布之后&#xff0c;华为Nova系列、荣耀数字系列会跟着发布&#xff1b;另一个则是年底的华为Mate系列发布之后&#xff0c;华为Nova新系列和荣耀V系列也会一起发布。现在已经是9月底&#xff0c;再等不到一个月的时…

docker服务无法启动 神坑

背景环境 centos6 docker1.7 service docker status输出&#xff1a; docker dead but subsys locked 各种找资料 尝试&#xff1a; rm -rf /var/run/docker.* rm -rf /var/lock/subsys/docker &#xff08;备注&#xff1a;如果有需要备份的docker此处千万不要用rm -r…