Android事件分发机制

本文由本人原创,转载请注明作者

Android中的事件分发机制是新手学习的一个重难点。而且往往学习了之后以为掌握的差不多了,但遇到新问题的时候又发现没有掌握到位或者又忘掉了。笔者就是这种情况,因此将自己已掌握的事件分发机制记录下来,作为记录和交流。

一、背景目的

  • 什么是Android事件分发机制?

事件分发机制是处理Android各种滑动冲突的理论基础,也是学习Android的核心知识点,掌握好View和ViewGroup的事件分发机制是十分重要的。

  • 为什么Android要设计一套事件分发机制?

当父控件和子控件都可以响应用户输入作出行为的时候(比如触摸滑动),这时候就会造成事件冲突。如何判断用户的输入事件由父控件处理还是子控件处理,就需要设计出一套规则了,这套规则就是Android事件分发机制。

  • 没有子父关系的控件会出现事件冲突吗?

没有子父关系的控件,它们是不会产生事件冲突的。因此在处理事件冲突的时候,首先要分析产生冲突的子控件是哪一个,父控件是哪一个。

二、基础知识

  • View和ViewGroup

Android中的控件大致可以分为两类,分别是View和ViewGroup。其中ViewGroup实际上也是继承自View。ViewGroup表示可以拥有子控件的控件,常见的有LinearLayout、ListView这些。后面我们将通过学习知道,在Android事件分发机制中,View是没有拦截方法的,而ViewGroup的拦截方法没有重写的话默认也是不进行拦截的。

  • MotionEvent分类

Android设备可以接收的事件总类很多,比如按压、拖拽、滑动,这些事件分类是由android底层完成的。总的来说,用户操作可以分为三类,及MotionEvent中的ACTION_DOWN(按下),ACTION_MOVE(移动),ACTION_UP(抬起)。从用户手指按下到抬起这一连串的事件被称之为一个事件序列。关于事件序列,下面也会说到。

三、事件分发流程

图片来自网络

从这张图片来看一次点击事件的传递。在这张图中有三个存在子父View关系的View,其中上面两个能作为父View的自然是属于ViewGroup了。

ViewGroup—dispatchTouchEvent方法

Touch事件发生后,顶级父View先接受到消息,此时会先调用顶级View的dispatchTouchEvent方法,这在图片上没有画出来。该方法的返回true的话,代表事件被消费掉了(当事件被消费时便不再传递);返回false的话事件不再往下传递,由上一级View的onTouchEvent方法来处理。如果没有重写该方法的话(即调用ViewGroup中的dispatchTouchEvent方法),会判断onInterceptTouchEvent的返回值来确定下一步传递方向。

ViewGroup—onInterceptTouchEvent方法

该方法顾名思义,判断当前View是否拦截该事件。如图所示,返回Ture的话会拦截事件传递,调用顶级View的onTouchEvent方法来处理事件。返回false的话表示不中断,事件继续向下传递。传递到下一级父View的过程也是一样,onInterceptTouchEvent方法返回false的话会一直向下传递到子View。

View-dispatchTouchEvent方法

View的dispatchTouchEvent方法跟ViewGroup是有区别的。通过看源码可以知道,View没有onInterceptTouchEvent方法,因此也它会直接调用onTouchEvent方法来判断事件是否被消耗。另外如果View被设置了各种Listener(如OnClickListener)之后,对应的事件也会随着Listener中对应的方法返回true而被消耗。

View—onTouchEvent方法

传递到子View的时候会调用子View的dispatchTouchEvent方法,一般自定义View的时候在onTouchEvent中处理与用户触摸按压的交互逻辑。不管该方法过程如何,如果onTouchEvent的返回值为True表示事件被消耗,事件不再传递。反之,事件将向上传递,传给父View去处理。另外需要注意的是当View的clickable和longClickabale属性同时为false的时候,代表View不可点击(如TextView),因此onTouchEvent方法也会默认返回false不消耗事件。

ViewGroup—onTouchEvent方法

ViewGroup对onTouchEvent的方法和View一样,返回true的话代表事件被消耗,返回false将事件继续向上传递。具体的行为要看具体的重写方法。

四、总结分发流程

可以看到事件传递时是一层层向下传递接受,再由下往上进行处理。这和现实工作也很类似:

产品经理提了一个新的需求,高级程序员接到需求先考虑下要不要自己做(onInterceptTouchEvent方法过程),觉得应该自己处理就自己完成了(ViewGroup—onTouchEvent方法过程);觉得应该由下属去做就下发给见习程序员,见习程序员没有下属只能自己去处理(View—onTouchEvent方法过程);见习程序员如果很好地解决需求了(onTouchEvent方法返回true),这个事件就到此结束了。如果需求太难,见习程序员处理不了这个需求(onTouchEvent方法返回false),那么就会再交给上级去处理。

可见Google的程序员在设计这些代码时的用的方法十分巧妙,也是和现实相结合地去设计代码,对于开发者也便于理解。
任玉刚大神在《Android开发艺术探索》一书中对事件分发机制的讲解十分到位,推荐有兴趣的朋友去看看。书中用一段伪代码把事件分发机制抽象的非常清楚:

public boolean dispatchTouchEvent(MotionEvent event) {
    boolean consume =false;
    if(onInterceptTouchEvent(ev)) {
        consume = onTouchEvent(ev);
    } else {
        consume = child.dispatchTouchEvent(ev);
    }
    return consume;
}

其中comsume代表事件是否被消耗。当事件传递到ViewGroup的时候,先判断是否拦截。拦截的话由自己的onTouchEvent方法处理;不拦截的话,分发给子View处理,调用子View的dispatchTouchEvent方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容