View 事件分发
View 事件分发
学习自
《Android开发艺术探索》
官方文档-MotionEvent
事件分发机制漫谈
View的事件分发机制,使我们了解View的工作原理继而学习如何自定义View的基础,尽管这些知识比较理论,但是还是很有必要了解其原理的,知其然不知其所以然是不可取的。
MotionEvent重提
我们在之前已经提到了MotionEvent对象也多少有些应用,但是并没有对其太过关注,而MotionEvent正式View事件分发机制的核心,我们有必要重新认识一下它,我们来看一下权威的官方文档。
Object used to report movement (mouse, pen, finger, trackball) events.Motion events may hold either absolute or relative movements and other data,depending on the type of device.
MotionEvent是被用来报道移动动作(鼠标,笔,手指,轨迹球)事件的对象。此对象可以基于设备类型持有绝对或相对的移动动作的数据和其他有关的数据。
通过官方文档了到了MotionEvent中存储的就是我们的 触屏
的信息,而Android对事件的处理正是对我们与设备的手势的交互的相应,View的事件的处理就是围绕着MotionEvent来展开的。
三个重要的方法
View事件的分发机制就是对MotionEvent的分发,最终将其传递给一个具体的View,这就是View事件的分发过程。在这个过程中有3个很重要的方法,接下来一起来看一看。
再看这三个方法之前我们需要先来了解一个概念----事件序列
事件序列指的是,从手指按下屏幕开始到手指离开屏幕期间所产生的事件,事件序列的第一个事件是 __down __最后一个事件是 up。
dispatchTouchEvent
下面是此方法的方法签名,此方法的作用是将MotionEvent分发给目标View,其返回值代表的是,处理MotionEvent事件的是否是当前View.
public boolean dispatchTouchEvent(MotionEvent event)
onInterceptTouchEvent
此方法会在 dispatchTouchEvent
方法中调用,此方法的作用就是过滤掉那些不符合胃口的MotionEvent. 返回值是否拦截当前事件。如果此方法返回为 ture
那么在同一事件序列中该方法不会被再次调用。
public boolean onInterceptTouchEvent(MotionEvent ev)
onTouchEvent
此方法用来处理触屏的MotionEvent,如果返回ture表示MotionEvent已经被处理,否则反之。
public boolean onTouchEvent(MotionEvent event)
调用流程
当一个MotionEvent产生时,顶级的
ViewGroup的 dispatchTouchEvent
方法将会被调用,如果此时 onInterceptTouchEvent
方法返回为 ture
那么表示拦截当前的事件,此事件将会交给ViewGroup本身去执行,如果返回 false
那么事件会继续传递给 子View
,如此往复直到事件被处理。
OnTouchListener
如果一个View设置了OnTouchListener事件那么这时候需要注意了,如果返回为 ture
则不会调用 onTouchEvent
方法,因为onClick事件是在onTouchEvent方法中调用的所以,如果此时设置 onClick事件,onClick事件是不会执行的。由此可见onClick事件位于事件分发的末端部位。
一个特殊的情况
当一个事件产生的时候,是按照以下的顺序进行传递的: Activity->Window->View. 当顶级的View即ViewGroup接收到事件后,会向子View进行分发,如果子View拒绝对事件进行处理的话,那么事件就会返回值父View进行处理,要是有的View都不对事件进行处理的话,那么这时候事件就会重新返回给Activity处理 ,即Activity的onTouchEvent方法将会被调用。
归纳
下面是《Android开发艺术探索》的作者-任玉刚老师对View事件分发的一些总结。
- 正常情况下一个事件序列只能够被一个View拦截。这一条可以参考(2),因为一旦一个元素拦截了某此事件,那么同一个事件序列内的所有事件都会直接交给它处理,因此同一个事件序列中的事件不能分别由两个View同时处理,但是通过特殊手段可以做到,比如一个View将本该 自己处理的事件通过 onTouchEvent强行传递给其他View处理。
- 某个View一旦决定拦截,那么这一个事件序列都只能由它来处理〈如果事件序列能够传递给它的话),并且它的onInterceptTouchEvent不会再被调用。这条也很好理解,就是说当一个View决定拦截一个事件后,那么系统会把同一个事件序列内的其他方法都直接交给它来处理,因此就不用再调用这个View的onJnterceptTouchEvent去询问它是否要拦截了。
- 某个View一旦开始处理事件,如果它不消耗ACTION_DOWN事件(onTouchEvent返回了false), 那么同一事件序列中的其他事件都不会再交给它来处理,并且事件将重新交由它的父元素去处理,即父元素的onTouchEvent会被调用。意思就是事件一旦交给一个View处理, 那么它就必须消耗掉,否则同一事件序列中剩下的事件就不再交给它来处理了,这就好比上级交给程序员一件事,如果这件事没有处理好,短期内上级就不敢再把事情交给这个程序员做了,二者是类似的道理。
- 如果View不消耗除ACTION_DOWN以外的其他事件, 那么这个点击事件会消失,此时父元素的onTouchEvent并不会被调用,并且当前View可以持续收到后续的事件,最终这些消失的点击事件会传递给Activity处理。
- ViewGroup 默认不拦截任何事件。Android源码中ViewGroup的onInterceptTouchEvent方法默认 返回false。
- View没有onInterceptTouchEvent方法,一旦有点击事件传递给它,那么它的onTouchEvent方法就会被 调用。
- View的onTouchEvent 默认 都会消耗事件(返回true), 除非它是不可点击的(clickable和longClickable同时为false)。View的longClickable属性默认都为人alse,clickable属性要分情况,比如Button的clickable属性默认为true, 而TextView的clickable属性默认为false。
- View的enable属性不影响onTouchEvent的默认 返回值。哪怕一个View是disable状态的,只要它的clickable或者 longClickable有一个为tue,那么它的onTouchEvent就返回true。
- onClick会发生的前提是当前View是可点击的,并且它收到了down和up的事件。
- 事件传递过程是由外向内的,即事件总是先传递给父元素,然后再由父元素分发给子View,通过requestDisallowInterceptTouchEvent方法可以在子元素中干预父元素的事件分发过程,但是ACTION_DOWN事件除外。
View 事件分发的更多相关文章
- Atitit View事件分发机制
1. Atitit View事件分发机制 1. Atitit View事件分发机制1 1.1. 三个关键方法 dispatchTouchEvent onInterceptTouchEvent onTo ...
- Android View框架总结(七)View事件分发机制
请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52282833 View布局告一段落,从本篇开始View事件相关分析, ...
- Android View事件分发-从源码分析
View事件分发-从源码分析 学习自 <Android开发艺术探索> https://blog.csdn.net/qian520ao/article/details/78555397?lo ...
- Android面试必问!View 事件分发机制,看这一篇就够了!
在 Android 开发当中,View 的事件分发机制是一块很重要的知识.不仅在开发当中经常需要用到,面试的时候也经常被问到. 如果你在面试的时候,能把这块讲清楚,对于校招生或者实习生来说,算是一块不 ...
- Android View 事件分发机制 源码解析 (上)
一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~ 首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个My ...
- android View事件分发机制结论
原始博客有对源码的分析:http://blog.csdn.net/lmj623565791/article/details/39102591 结论:1.view事件的分发流程: dispatchTou ...
- View事件分发机制
所谓的事件分发,其实就是对MotionEvent事件的分发过程,即当一个MotionEvent产生后,系统需要把这个事件传递给一个具体的View,而这个传递的过程就是分发过程. 点击事件的分发由3个方 ...
- Android View 事件分发机制详解
想必很多android开发者都遇到过手势冲突的情况,我们一般都是通过内部拦截和外部拦截法解决此类问题.要想搞明白原理就必须了解View的分发机制.在此之前我们先来了解一下以下三个非常重要的方法: di ...
- 自定义控件(视图)2期笔记10:自定义视图之View事件分发机制("瀑布流"的案例)
1. Touch事件的传递: 图解Touch事件的传递,如下: 当我们点击子View 02内部的Button控件时候,我们就触发了Touch事件. • 这个Touch事件首先传递给了顶级父View ...
随机推荐
- vue.js初识(一)
vue.js安装 官网:http://cn.vuejs.org/ 官方安装介绍:http://cn.vuejs.org/v2/guide/installation.html MVVM框架:View.V ...
- Vue单页面应用阻止浏览器记住密码
Vue单页面应用阻止浏览器记住密码 ——IT唐伯虎 摘要: Vue单页面应用阻止浏览器记住密码. 现象1:路由切换时再次提示“是否记住密码” 登录页面有个密码输入框,输入账号密码进行登录: 登录完成后 ...
- 【前端安全】JavaScript防XSS攻击
什么是XSS XSS(Cross Site Scripting),跨站脚本攻击,是一种允许攻击者在另外一个用户的浏览器中执行恶意代码脚本的脚本注入式攻击.本来缩小应该是CSS,但为了和层叠样式(Cas ...
- disabled属性对form表单向后台传值的影响
在form表单里,如果对input加入disabled="disabled"或disabled="true"等属性,form表单提交的时候,就不会传值到后台. ...
- bug处理
当提示405 method not allowed 时候,路由可能有问题,看看路由是get/post 是否合格
- 用MFC(C++)实现拼音搜索
2015年4月1日更新: 我在github开源了Objective-C版的拼音搜索项目,感兴趣的可以去看看: OC版拼音搜索 最近项目需要实现按照拼音搜索资源.在网上找了一下,这方面的东西太少了. J ...
- Windows::Docker::Ubuntu 做 SLAM
如题,这是一件很蛋疼的事情. 为了完成这一件事情,需要达成目标: Ubuntu GUI 必须要能够显示. Ubuntu 可以链接 USB Camera. 目标一 目标1很容易达成. 在 Win10 中 ...
- deeplearning.ai学习LSTM
一.LSTM架构与公式 这里的a<t>表示的就是原始输出,y<t>表示的就是经过softmax的输出,c<t>相当于状态.u(update)代表是输入门,f代表遗忘 ...
- python3操作数据库 借助pycharm快速连接并操作mysql数据库
1.https://blog.csdn.net/qiushi_1990/article/details/78041299
- RESET MASTER和RESET SLAVE使用场景和说明【转】
[前言]在配置主从的时候经常会用到这两个语句,刚开始的时候还不清楚这两个语句的使用特性和使用场景. 经过测试整理了以下文档,希望能对大家有所帮助: [一]RESET MASTER参数 功能说明:删除所 ...