View的事件拦截机制浅析

为什么要去分析view的事件

记得上周刚立的flag就是关于view的事件机制。那现在我来说说我对view的感受。关于view的事件,百度google一搜。一批又一批。但是能让人理解的少之又少。换句话说,不是那些作者不懂。只是说,他懂了,但他讲解后不一定能让别人看得懂。我记得有人问我当初是怎么接触自定义view这东西的。因为他们觉得自定义view这个东西很难。我就回了如下几句话:自定义view你把paint和canvas。弄懂了基本也就差不多了。我这边说的是差不多,不是完全,你们别曲解哈= =当然前提是数学和物理要好= =。对于View来说,我认为,paint和canvas都不是重点,如何分析他的事件处理才是重点。下面我们一步步的来了解。

View的结构

想要了解view的事件,他的结构我们是需要知道的,我们先放一张view的结构图。然后根据图来一步步分析:

最顶层的PhoneWindow是什么呢?通过字面意思,我们知道他是手机窗口。我们需要知道window到底是什么才能分析phonewindow的作用。

简单来说,Window是一个抽象类,是所有视图的最顶层容器,视图的外观和行为都归他管,不论是背景显示,标题栏还是事件处理都是他管理的范畴,虽然能管的事情看似很多,但是没实权,因为抽象类不能直接使用。

而 PhoneWindow 作为 Window 的唯一实现类,PhoneWindow 的权利可是非常大大,不过对于我们来说用处并不大。

下面我们来说说DecorView:

这样,我们做个假设,一个跟布局高度是wrap的控件,我们运行之后可以发现,除了那个控件,留下了大量的空白区域,由于我们的手机屏幕不能透明,所以这些空白区域肯定要显示一些东西,那么应该显示什么呢?当然如果你没有设置全屏。我们还会发现标题栏状态栏那些。而这些就是所谓的DecorView。

事件处理的过程

我们先看下下面的表格:

从上表可以看到 Activity 和 View 都是没有事件拦截的,这是因为:

  1. Activity 作为原始的事件分发者,如果 Activity 拦截了事件会导致整个屏幕都无法响应事件,这肯定不是我们想要的效果。
  2. View最为事件传递的最末端,要么消费掉事件,要么不处理进行回传,根本没必要进行事件拦截。

所以我们知道了activity是最上层,而view是最底层,那么结合之前view的结构的那张图,我们可以知道view的传递流程应该是这样:

而view的处理恰恰相反,那就是这样:

如果上面的你理解了,下面这张图,对你来说也就是小意思了。

如果你已经完全理解了上面的内容。那么对于view的事件处理。你已经懂了50%了。

事件分发和拦截

事件分发和拦截的流程其实就是上面那张图。《群英传》中举得例子很恰当。我们现在也对所有的流程对应一个职位:

前面已经知道了处理流程,我们这边在写一次。

分发(dispatch)–>拦截(onIntercept)–>消费(ontouch)

public boolean dispatchTouchEvent(MotionEvent ev)

用来进行事件分发。如果事件能够传递到当前view。那么此方法一定会调用,返回结果受当前View的ontouch和下级的dispatchtouchevent影响,表示是否消耗当前事件。

public boolean onInterceptTouchEvent(MotionEvent ev)

在上述方法内部调用,用来判断是否拦截事件,如果当前view拦截了事件,那么在同一序列中此方法不会在调用,返回结果表示是否拦截事件。

public boolean onTouchEvent(MotionEvent event)

在dispatch方法中调用,用来处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,那么当前view再也无法接受事件。

默认情况下,我们都是返回false。

默认的点击事件

我们先看下整体的效果图,再来进行点击查看结果:

当然这是一个framelayout。你们只要知道是一层盖一层就对了= = 。那么现在所有的事件我们直接return super来看下效果图:

我们通过上面列举的职位可以分析下情况,具体详情如下:

可以从log日志中看出,和我们上面的流程是一模一样的。我们尝试下对某个view的TouchEvent 直接拦截了(return true),然后在看看效果图:

流程应该就是这样:

那么我们如果ViewGroup进行拦截处理呢?也就是View的事件不响应了。我们再一次的看看效果图:

流程如下:

总结

综上所失,我们可以发现,我们几乎没有在dispatch里面进行任何处理,不是说用不到,只是这个方法用的不多,一般都在拦截和消费里面进行处理,通知上层或者下层是否需要执行。昨天一个小伙伴刚和我说他最近也在重新整理view这块,也是一个功能就要用到了dispatch这个方法。这个具体我就不细说了。你们可以自己理理。

这个篇幅我只是对view做了一个简单的介绍,通过标题“浅析”也知道。不过,如果这篇你们看懂了。对于正常的需求开发已无大碍。后面我尽可能去深入分析一次。

参考文献

《Android群英传》

事件分发机制原理

原文发布于微信公众号 - 我就是马云飞(coding_ma)

原文发表时间:2017-08-04

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏互联网杂技

前端各种优化

1.  请减少HTTP请求   基本原理:   在浏览器(客户端)和服务器发生通信时,就已经消耗了大量的时间,尤其是在网络情况比较糟糕的时候,这个问题尤其的突...

3428
来自专栏技术小黑屋

Android UI之自定义Window Title样式

Android提供了很多控件便于开发者进行UI相关的程序设计。但是很多时候,默认的一些UI设置不足以满足我们的需求,要么不好看,要么高度不够,亦或者是与应用界面...

2151
来自专栏腾讯社交用户体验设计

Origami五分钟入门秘籍 - 腾讯ISUX

1672
来自专栏小巫技术博客

高效Mac(三)面向程序员的交互设计神器:Framer Studio

813
来自专栏姬小光

姬小光前端兴趣班【第008期】- 真正的切图大法

上一期我们使用了 word 转存大法来生成网页,主要是为了帮助大家理解表格布局的原理。那么今天我们就来学习一下真正的切图大法。

1312
来自专栏思衍 Jax 专栏

企鹅辅导课程详情页毫秒开的秘密 - PWA 直出

随着近几年的前端技术的高速发展,越来越多的团队使用 React、Vue 等 SPA 框架作为其主要的技术栈。以 React 应用为例,从性能角度,其最重要的指标...

97111
来自专栏Android干货园

Android实现沉浸式通知栏,通知栏可以根据app的颜色可改变啦

版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/lyhhj/article/details/46...

1171
来自专栏java工会

前端进阶攻略|最全的前端开源JS框架和库

3657
来自专栏DannyHoo的专栏

iOS开发中在swift项目中使用Kingfisher下载图片

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010105969/article/details...

1684
来自专栏Python自动化测试

Frame在自动化中的处理

在自动化中,如果一个元素定位不到,那么最大可能是在iframe中,我们先了解frame。frame是html中的框架,在html中,所谓框架就是可以在同一个浏...

1363

扫码关注云+社区

领取腾讯云代金券