转载好文章:

http://blog.csdn.net/chunqiuwei/article/details/41084921

学了这么久的Android,面试也常被问到事件分发机制,但总感觉对这个机制还是不清不楚.突然之间

翻了一下李刚的<Crazy Android>,突然有了一些感悟,所以就立马记下来:

一、监听与回调

第一,要明白和事件相关的3个概念:事件源,事件,事件监听器.

事件源:就是事件作用的对象

事件:就是事件本身,可以是点击,长按,移动等等,就是XxxEvent.

事件监听器:就是Listener,一般写成内部类的形式,说白了,就是一个类,而这个类往往是事件源

内部的接口实现类。

第二,<Crazy Android>上总结得很到位:Android中的事件处理机制可以分为两大类,监听回调.

监听:就是给控件添加一个监听器,即addXxxListener(new XxxListener(){...}),事件源本身不直

接处理,而是交由事件监听器进行处理.

回调:当事件作用在事件源的时候,事件源本身会触发一些自己的方法,自己来处理事件.但往往事件

源的这些方法是封装在事件源对象的内部的,用户看不见.这也就是为什么需要有监听器的原

因,让用户知道事件源发生了什么事件.通常在自定义控件的时候,就需要复写和Touch相关的

事件,同时抽取监听器接口,让用户去实现.

-----------------------------------------------------------------------------------------

举个小例子:

假如有这样一个需求:点击一下Button,打印一条日志.

那么有2种实现方式

第1种实现方式-为Button设置监听器

Button.setOnClickListener(new OnClickListener(){

onClick(View view)

{

Log...

}

});

第2种实现方式-继承Button,自定义一个MyButton

定义的时候,复写Button的onTouchEvent方法,在里面打印日志.

那么,现在又有一个需求:点击一下Button,弹出一个吐司.

如果采用第1种方式,只要修改一下onClick里的代码.

如果采用第2种方式,那么1种办法是再创建一个Button的子类,另外一个方法就是修改原来

MyButton的onTouchEvent方法,但是这样一来又不能满足开始的需求了.

所以到这里,监听与回调的区别也就不言而喻了吧.

1)监听只是组件的作者在写回调方法时,暴露给用户的一个接口,这样用户可以实现接口,

达到自身的需求,最终用户实现的接口里的方法在组件的回调方法里会被回调。

二、结合2.3.3中View的源码,再谈监听与回调

1.View的dispatchTouchEvent方法

我之前一直没有搞清楚View的dispatchTouchEvent的返回值的作用,现在明白了,

返回true,作用在View上的触摸事件(包括Button的点击事件)就会生效;

返回false,作用在View上的触摸事件就失效。

但具体dispatchTouchEvent方法又在哪里被调用了呢(?????????????)

     public boolean dispatchTouchEvent(MotionEvent event) {。。。if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&mOnTouchListener.onTouch(this, event)) {return true;}return onTouchEvent(event);}

2)监听是先判断的,所以监听比回调的优先级要高。先判断listener.onTouch的返回值

,否则就return onTouchEvent(event)将事件交由组件的onTouchEvent回调方法进行处理。

所谓View的事件分发,解决的问题就是事件是由用户处理还是View自身处理。

三、结合2.3.3中ViewGroup的源码,再谈监听与回调

由于ViewGroup的dispatch事件源码过多,我就不一一写了,大致地去描述一下。

ViewGroup的dispatch事件干的事:

先弄一个变量来缓存可能会捕捉并处理事件的View,target.

在点击ev.getAction == MotionEvent.Action_Down的事件里

根据onIntercept事件判断自己需不需要拦截事件,如果不拦截,则遍历ViewGroup里的

每个子View,通过计算子View的矩形区域来判断点击事件的坐标有没有落在子View上,如果点

击事件的坐标落在子View并且子View捕捉并处理事件,那么target就等于这个子View。

判断target是否为null

如果为null,则调用ViewGroup的父类的dispatch事件,也就是把ViewGroup当作

View来处理。

如果不为null,则交由target.dispatch事件进行处理。

所谓ViewGroup的事件分发,解决的问题就是事件到底是由哪个View来处理。



四、FrameLayout的事件分发机制

我们都知道,ViewGroup的事件传递顺序是由父控件往子控件传递,但是假如是FrameLayout的两

个子控件重叠在一起,并且两个子控件没有包含(父子)关系,那么事件的传递顺序是怎样的呢

其实这个Android源码里已经说得十分地清楚了,

// Scan children from front to back.

也就是从上往下查找,自然事件也是从上往下传递。

1)在做《风口》项目时,我也遇到过这种问题:

明明点击的地方什么也没有,但是事件却被响应了。我将布局看来看去,想了很久,突然

明白这就是事件分发导致的。FrameLayout的上层Layout点击的位置没有控件响应事件,但是在下

一层的Layout中,鼠标点位的位置有控件响应。这种解释了这种见鬼的原因!

2)小资钱包首页,“马上抢购”按钮和它所在的父布局响应同样的事件。

第1种方法:给2者注册同一个监听器

第2种方法:屏蔽Button对事件的响应,只注册父布局的监听。(即怎么让按钮可点击但是不响

应点击事件)

复写Button onIntercept方法返回false.

转载于:https://blog.51cto.com/4259297/1702321

随我一起慢慢揭开Andoird里事件分发机制的神秘面纱相关推荐

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

    <div id="container">         <div id="header">     <div class=&qu ...

  2. View事件分发机制(源码 API27)

    1.什么是事件分发机制 当用户触摸屏幕时,会产生一个touch事件,这个touch事件(motionEvent)传递到某个具体的view处理的整个过程 用户触摸屏幕会产生一个事件流(ACTION_DO ...

  3. Android事件分发机制详解

    2019独角兽企业重金招聘Python工程师标准>>> 之前在学习Android事件方法机制的时候,看过不少文章,但是大部分都讲的不是很清楚,我自己理解的也是云里雾里,也尝试过阅读源 ...

  4. android触摸事件分发,Android 事件分发机制

    Android 事件分发机制一直让人头痛,之前也是面向 GitHub 编程得过且过.今天下定决心了解一下,以便后面自己定制 View 效果.Android 触摸事件有三个基本类型:ACTION_DOW ...

  5. View事件分发机制(源码分析篇)

    01.Android中事件分发顺序 1.1 事件分发的对象是谁 事件分发的对象是事件.注意,事件分发是向下传递的,也就是父到子的顺序. 当用户触摸屏幕时(View或ViewGroup派生的控件),将产 ...

  6. 事件分发机制并不是洪水猛兽

    文章目录 OnTouchListener与OnClickListener的优先级 事件分发 滑动冲突 处理滑动冲突 1. 内部拦截法 2.外部拦截法 当MotionEvent产生后,系统总归要将其传递 ...

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

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

  8. Android View的事件分发机制解析

    作者:网易·周龙 最近刚看完android-Ultra-Pull-To-Refresh下拉刷新的源码,发现在写自定义控件时,对于View的事件的传递总是搞不太清楚,而View事件的分发机制,又是解决可 ...

  9. Android 事件分发机制

    Android 事件分发机制  demo验证:  https://blog.csdn.net/hty1053240123/article/details/77866302 目录 1.基础认知 2.事件 ...

最新文章

  1. 为什么TCP建立连接需要三次握手
  2. TEETrustZone
  3. python知识:@classmethod和@staticmethod的异同
  4. 4412 字符类设备的设备号
  5. 光缆故障测试_简单的测试可以防止最严重的故障
  6. ambari mysql jar_从零开始安装 Ambari (3) -- 安装 Ambari
  7. npm+node+cordova+ionic 版本匹配
  8. [图像处理]指定任意灰度变换
  9. abb机器人伺服电机报闸是什么_ABB机器人伺服电机维修更换马达步骤
  10. 数字电路 逻辑函数的化简之 公式化简法
  11. oracle中文转全拼音,汉字转拼音的Oracle函数
  12. UE4 替换文件尝试解决 光照构建失败 Lighting build failed. Swarm failed to kick off
  13. oblog商业版本4.6注射漏洞,直接拿管理员
  14. 【PSO三维路径规划】基于matlab球面矢量粒子群算法无人机三维路径规划【含Matlab源码 1682期】
  15. Python数据分析基础(2)
  16. matplotlib中文字体设置
  17. 客户/供应商主数据批导
  18. 【PX4-AutoPilot教程-1】PX4源码文件目录架构分析
  19. Xilinx 7系列FPGA config设计文档
  20. STS项目报红,maven导入

热门文章

  1. 在非华为电脑上使用华为多屏协同
  2. 标准正态分布函数和反函数Ф^(-1)
  3. 路径规划算法--PRM,从原理到Matlab实现
  4. 华为OD机试 - 转骰子
  5. php中什么是形参和实参,形参和实参的概念
  6. python strftime_python 中strftime用法
  7. 使用 VMware 装一个 fedora 虚拟机并设置共享文件夹的平凡之路…
  8. cvCircle()函数
  9. 关于洛必达法则的一些验证
  10. 流媒体系统包括哪三部分?目前三大主流媒体格式以及协议是什么?