自己定义Viewgrou中我们或许会常常碰到这种情况,2个子控件的事件冲突导致滑动没实用了。滑动反应非常慢,点击没用了,要划非常多次才移动一点点等等。或许我们第一反应就是百度,google去搜索下答案,把代码直接copy过来。事实上或许能够换个解决的方法。自己想想为什么会出现这种情况。

下面是博主对android事件分发机制的探索。希望大家看完后能对Android事件分发机制有一个具体的了解,以后不用百度。google也能轻松解决因为事件冲突导致各种问题。

首先我们要对Android 事件有初步的了解:

1.Android  Touch事件相关的函数包含了:

dispatchTouchEvent(MotionEvent ev):负责事件分发的函数,在各个view里面最先被调用

onInterceptTouchEvent(MotionEvent ev) :事件拦截的函数(viewGroup很重要函数,以下会有详细说明)

onTouchEvent(MotionEvent ev):事件响应的函数

onTouch(MotionEvent ev):事件响应的函数

onTouchEvent(MotionEvent ev)和onTouch(MotionEvent ev)均是事件响应的函数,2者差别:onTouch会优先于onTouchEvent调用,onTouch仅仅有在listener不为空与点击的控件为enable的情况下会被调用,onTouch能通过控件外部传入onTouchListener来实现监听,而onTouchEvent不能通过外部设置。(可能描写叙述过于抽象,简单点就是有些控件没有ontouch事件,或者控件不可点击那么我们想监听onTouch事件就必须重写onTouchEvent来实现监听)

请看下面view的dispatchTouchEvent源代码中调用onTouch()和onTouchEvent()的差别:

if (onFilterTouchEventForSecurity(event)) {
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
} if (!result && onTouchEvent(event)) {
result = true;
}
}

外层推断临时无论(用来推断view是否位于顶部的,假设view不在顶部,过滤掉用户点击事件),请注意内层推断。当mListenerInfo中的mOnTouchListener不为空(即我们给view注冊了监听事件)而且view是可点击的就把事件交给mListenerInfo的mOnTouchListener.onTouch来处理而且依据onTouchListener的boolean来决定事件是否继续传递。依据result的值来决定是否调用onTouchEvent

返回值说明:当dispatchTouchEvent(MotionEvent ev)返回为false表示继续向上传递,true表示停止传递



下面是事件传递的顺序:

假定我们有一个LinearLayout,   布局中有一个Button。那么touch事件的传递例如以下:

activity的dispatchTouchEvent()------>LinearLayout的dispatchTouchEvent()--------->onInterceptTouchEvent()------->button的dispatchTouchEvent()从根元素向上依次传递,假设中间我们重写了某view的dispatchTouchEvent()而且返回true,那么事件会停止继续传递而且由当前函数消费。onTouch和onTouchEvent一样的道理(这两者差别见上面描写叙述)。仅仅是顺序正好和dispatchTouchEvent的顺序相反,从最外层向根元素传递。

至于onInterceptTouchEvent(),首先该函数是ViewGroup的函数,也意味着仅仅有ViewGroup和该类的子类中能够重写该函数,比如我们自己定义的view继承自LinearLayout(LinearLayout为ViewGroup的子类),那么我们就能够重写该函数来达到事件拦截的目的。该函数紧跟dispatchTouchEvent()后调用(前提是该函数存在,默认返回false),假设onInterceptTouchEvent()返回为false 事件会继续传递,假设返回为true。那么事件将停止继续向上面的dispatchTouchEvent()而且将事件交给自己的onTouch()和onTouchEvent()来处理。

以下我们来看下实验的结果

1.没有改变事件返回的结果

事件终于被customButton消费掉了,从中我们能够得到下面事件传递的图

2.重写onInterceptTouchEvent,而且返回为true截断事件继续传递

这里须要说明下因为在coustomLinearLayout中事件没有被消费掉(也就是Touch相关函数所有返回为false)。假设是activity分发下去的事件那么终于会到由activity onTouchEvent()消费掉,以下是调用的示意图

3.CustomButton的onTouchEvent()返回false

4.点击在CustomLinearLayout上,没有点击到CustomButton

从上面我们能够得到

1.除了onInterceptTouchEvent()外。其它事件依照1所看到的依次由根元素传递给点击的view,而且由view消费掉,而且中间环节随意一个函数返回了true(除了onInterceptTouchEvent()外),那么事件将会由当前返回true的函数消费,停止向后面传递,因为函数过多,博主就没有把每一个函数返回true的情况截图贴出来了。

2.ViewGroup的子类中。重写onInterceptTouchEvent()函数,返回为true,那么该函数将停止向子view的dispatchTouchEvent()传递。并把事件交由当前view的onTouch()和onTouchEvent()处理

3.view的onTouchEvent默认会消费掉事件。ViewGroup的0nTouchEvent则不会消费掉事件

4.同级别view,会依据你点击的控件来进行事件传递,传递到对应的你点击的view,假设点击的是ViewGroup,那么事件将不会被消费掉,直到传递到分发的根元素的OnTouchEvent()才会被消费掉

兴许补充:

偶然回想非常久之前写的这篇博客,发现有关dispatchTouchEvent()函数的处理有些情况未做说明,easy导致读者出现误会,特此补充,

ViewGroup中dispatchTouchEvent()的返回值分为3种情况:

1.返回false 停止事件向上的传递.调用上级传递者的onTouchEvent()处理

2.返回true   
消费掉该次事件,终止事件传递


3.调用super返回     正常向下传递

说明:关于向下向上传递,仅仅是个人理解的不同,我理解的事件分发模型类似一根立起来的管道,事件的传递从地面流向管道顶层,再流回到地面.正好符合视图叠加的流程.并不一定说这样的就是对的,方便自己理解的就是好的,看官也不必纠结于这点,关键是去理解中间事件分发的流程

掌握了以上的的事件传递的基本知识。下次我们碰到事件冲突就能够尝试自己去攻克了!

【自己定义控件】android事件分发机制的更多相关文章

  1. Android-自定义控件之事件分发

    最大范围 外层蓝色区域是继承ViewGroup 中间红色区域,也是继承ViewGroup 最中间黑色区域,是继承View 布局相关的代码: <!-- 事件分发 --> <view.c ...

  2. Android事件分发机制(下)

    这篇文章继续讨论Android事件分发机制,首先我们来探讨一下,什么是ViewGroup?它和普通的View有什么区别? 顾名思义,ViewGroup就是一组View的集合,它包含很多的子View和子 ...

  3. 【转】Android事件分发机制完全解析,带你从源码的角度彻底理解(下)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9153761 记得在前面的文章中,我带大家一起从源码的角度分析了Android中Vi ...

  4. 【朝花夕拾】Android自定义View篇之(六)Android事件分发机制(中)从源码分析事件分发逻辑及经常遇到的一些“诡异”现象

    前言 转载请注明,转自[https://www.cnblogs.com/andy-songwei/p/11039252.html]谢谢! 在上一篇文章[[朝花夕拾]Android自定义View篇之(五 ...

  5. Android事件分发机制(上)

    Android事件分发机制这个问题不止一个人问过我,每次我的回答都显得模拟两可,是因为自己一直对这个没有很好的理解,趁现在比较闲对这个做一点总结 举个例子: 你当前有一个非常简单的项目,只有一个Act ...

  6. android事件分发机制

    android事件分发机制,给控件设置ontouch监听事件,当ontouch返回true时,他就不会走onTouchEvent方法,要想走onTouchEvent方法只需要返回ontouch返回fa ...

  7. [转]Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

    Android事件分发机制 该篇文章出处:http://blog.csdn.net/guolin_blog/article/details/9097463 其实我一直准备写一篇关于Android事件分 ...

  8. 【朝花夕拾】Android自定义View篇之(五)Android事件分发机制(上)Touch三个重要方法的处理逻辑

    前言 转载请注明,转自[https://www.cnblogs.com/andy-songwei/p/10998855.html]谢谢! 在自定义View中,经常需要处理Android事件分发的问题, ...

  9. 【朝花夕拾】Android自定义View篇之(七)Android事件分发机制(下)滑动冲突解决方案总结

    前言 转载请声明,转自[https://www.cnblogs.com/andy-songwei/p/11072989.html],谢谢! 前面两篇文章,花了很大篇幅讲解了Android的事件分发机制 ...

随机推荐

  1. Mysql中的索引()key 、primary key 、unique key 与index区别)

    CREATE TABLE pre_forum_post ( pid int(10) unsigned NOT NULL COMMENT '帖子id', fid mediumint(8) unsigne ...

  2. bindColumn、bindParam与bindValue的区别

    bindColumn:绑定一列到一个 PHP 变量(类似于list()函数为变量赋值) <?php //连接数据库函数 functionconnect() { try { $dbh = new ...

  3. Android FrameWork 学习之Android 系统源码调试

    这是很久以前访问掘金的时候 无意间看到的一个关于Android的文章,作者更细心,分阶段的将学习步骤记录在自己博客中,我觉得很有用,想作为分享同时也是留下自己知识的一些欠缺收藏起来,今后做项目的时候会 ...

  4. (转)Struts2快速入门

    http://blog.csdn.net/yerenyuan_pku/article/details/66187307 Struts2框架的概述 Struts2是一种基于MVC模式的轻量级Web框架, ...

  5. 一个ROS的服务,使机器人向前移动指定距离

    源代码有点长,放文末链接里了. 服务描述及代码现在的服务是:请求时携带要前进的距离,然后底盘前进相应距离.代码如下,改动很小: #!/usr/bin/env python import rospyfr ...

  6. JSON,对象..的数据格式

    [此案例为自动产生的随机数] 对象: {a1:180,a2:721, a3:574} 序列化传值:将对象转化为Json字符串 public ActionResult Val2() { Random r ...

  7. sublime text3 verilog代码编写高级操作篇

    2018.10.21 好久没写博客了,这段时间一直在学习一直在沉淀,然而发现学的越多会的更少,只能快马加鞭吧! 博主从大一暑假接触FPGA,到现在快一年半了,时间恍逝.刚开始入门也是用的quartus ...

  8. pandas格式化str为时间,pandas将int转化为str

    code_300['HISTORY_DATE'] = code_300['HISTORY_DATE'].map(str)code_300['HISTORY_DATE'] = pd.to_datetim ...

  9. CentOS / RHEL 7 : Chrony V/s NTP (Differences Between ntpd and chronyd)

    CentOS / RHEL 7 : Chrony V/s NTP (Differences Between ntpd and chronyd) Chosing between Chrony and N ...

  10. 【解题报告】 洛谷 P3492 [POI2009]TAB-Arrays

    [解题报告] 洛谷 P3492 [POI2009]TAB-Arrays 这题是我随机跳题的时候跳到的.写完这道题之后,顺便看了一下题解,发现只有一篇题解,所以就在这里顺便写一个解题报告了. 首先当然是 ...