Touch事件机制
1、概念
Touch事件分发中有三个主角:Activity、ViewGroup和View。Activity的Touch事件事实上是调用它内部的ViewGroup的Touch事件,可以直接当成ViewGroup处理。
View在ViewGroup内,ViewGroup也可以在其他ViewGroup内,这时候把内部的ViewGroup当成View来分析。
View的相关事件只有两个:dispatchTouchEvent、onTouchEvent。ViewGroup的相关的事件在View的基础上则多一个事件onInterceptTouchEvent,只对ViewGroup可响应的事件进行拦截处理。
2、理解模型
整个ViewGroup处理流程,可以看做是Touch事件在以ViewGroup为中间节点的树状结构中寻找响应。
- 如果用户执行一个ACTION_DOWN事件,当前View的onInterceptTouchEvent返回true,则该事件和后续的ACTION_MOVE和,ACTION_UP将不再传递到View的子控件,而是直接交由该View的onTouchEvent来处理。
- 如果上面onInterceptTouchEvent返回false,则该事件和后续的ACTION_UP,ACTION_MOVE将也会透过onInterceptTouchEvent,继而传递到子控件的onInterceptTouchEvent。
- 如果该View的onInterceptTouchEvent返回false,事件传递到目标View,然后目标View的onTouchEvent又返回了false,那么事件将继续传递到目标View的上一级的onTouchEvent。如果目标View的onTouchEvent方法返回了true,说明此事件已被处理了。
3、几条基本规则
1.如果在某个层级没有处理ACTION_DOWN事件,那么该层就再也收不到后续的Touch事件了直到下一次ACTION_DOWN事件。
说明:a.某个层级没有处理某个事件指的是它以及它的子View都没有处理该事件。
b.这条规则不适用于Activity层(它是顶层),它们可以收到每一个Touch事件。
c.如果没有处理ACTION_MOVE这类事件,不会有任何影响。
2.如果ACTION_DOWN事件发生在某个View的范围之内,则后续的ACTION_MOVE,ACTION_UP和ACTION_CANCEL等事件都将被发往该View,即使事件已经出界了。
3.第一根按下的手指触发ACTION_DOWN事件,之后按下的手指触发ACTION_POINTER_DOWN事件,中间起来的手指触发ACTION_POINTER_UP事件,最后起来的手指触发ACTION_UP事件(即使它不是触发ACTION_DOWN事件的那根手指)。
4.pointer id可以用于跟踪手指,从按下的那个时刻起pointer id生效,直至起来的那一刻失效,这之间维持不变。
5.如果一个ACTION_DOWN事件被父View拦截了,则任何子View不会再收到任何Touch事件了(这符合第1点的要求)。
6.如果一个非ACTION_DOWN事件被父View拦截了,则那些上次处理了ACTION_DOWN事件的子View会收到一个ACTION_CANCEL事件,之后不会再收到任何Touch事件了,即使父View不再拦截后续的Touch事件。
7.如果父View决定处理Touch事件或者子View没有处理Touch事件,则父View按照普通View的处理方式处理Touch事件,否则它根本不处理Touch事件(它只负责分发)。
8.如果父View在onInterceptTouchEvent中拦截了事件,则onInterceptTouchEvent中不会再收到Touch事件了,事件被直接交给它自己处理(按照普通View的处理方式)。
4、分层理解
View层:
View的onTouch方法代码比较多,主要的逻辑分两步:
- 先是将事件交给TouchDelegate处理(如果有的话),如果TouchDelegate没有处理再自行处理;
- 自行处理主要负责View状态的变换(如按下状态),长按事件,点击事件的检测与触发等。
ViewGroup层:
ViewGroup层处理Touch事件的总体逻辑是:
- 先检测是否需要拦截,没有拦截的话下发给子View处理
- 如果子View没有处理再自行处理,自行处理的逻辑与View一样
拦截的逻辑是,将从down到up之间的所有事件看作一组事件,如果从down就拦截了,则组内的后续其它事件完全交给自己处理,不需要再进入拦截逻辑了;如果是从中间拦截,则先给子View发送cancel事件,组内的后续其它事件完全交给自己处理,不需要再进入拦截逻辑了。
分发的逻辑是,在ACTION_DOWN事件的时候,寻找子View进行处理,称为寻找Target;如果没有找到Target,则自行处理;如果找到Target,则交由Target处理。
从代码上看,dispatchTouchEvent负责分发逻辑,onTouchEvent负责真正的处理逻辑,一般应该重载onTouchEvent,只有特殊情况下才需要重载dispatchTouchEvent。
5、分发过程
dispatchTouchEvent是负责分发事件的,事件从activity传递出来之后,最先抵达便是最顶层view的dispatchTouchEvent,然后再进行分发,如果返回false,则交给这个view的interceptTouchEvent方法来决定是否要拦截这个事件,
- 如果interceptTouchEvent返回true,也就是拦截掉了,则交给它的onTouchEvent来处理,
- 如果interceptTouchEvent返回false,那么就传递给子view,由子view的dispatchTouchEvent再来开始这个事件的分发。
6、总结
Touch事件机制主要有三个重要动作:事件的分发、事件的处理和拦截。
事件的分发是在Activity和ViewGroup中进行,事件的拦截就只能在ViewGroup进行,而事件的处理则可以在三个主体都进行。
http://www.cnblogs.com/frydsh/archive/2012/11/08/2760408.html
http://www.open-open.com/lib/view/open1422428386548.html
http://blog.csdn.net/chenjie19891104/article/details/7014649
http://blog.csdn.net/fastthinking/article/details/21954245
Touch事件机制的更多相关文章
- React-Native系列Android——Touch事件原理及状态效果
Native原生相比于Hybrid或H5最大长处是具有流畅和复杂的交互效果,触摸事件便是当中重要一项,包括点击(Click).长按(LongClick).手势(gesture)等. 以最简单常见的点击 ...
- Android Touch事件传递机制 二:单纯的(伪生命周期)
转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...
- Android Touch事件传递机制 一: OnTouch,OnItemClick(监听器),dispatchTouchEvent(伪生命周期)
ViewGroup View Activity dispatchTouchEvent 有 有 有 onInterceptTouchEvent 有 无 无 onTouchEvent 有 有 有 例 ...
- Android touch 事件传递机制
前言: (1)在自定义view的时候经常会遇到事件拦截处理,比如在侧滑菜单的时候,我们希望在侧滑菜单里面有listview控件,但是我们希望既能左右滑动又能上下滑动,这个时候就需要对触摸的touch事 ...
- Android Touch事件传递机制解析 (推荐)
最近新闻列表里的下拉 down up move 等等让我十分头疼 ,无意间看到了一篇非常不错的帖子,转载如下: 开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把a ...
- Android Touch事件传递机制解析
android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法: 1)public boolean dispatchTouchEvent(MotionEven ...
- Android Touch事件传递机制通俗讲解
在讲正题之前我们讲一段有关任务传递的小故事,抛砖迎玉下: 话说一家软件公司,来一个任务,分派给了开发经理去完成: 开发经理拿到,看了一下,感觉好简单,于是 开发经理:分派给了开发组长 开发组长:分派给 ...
- (转)Android Touch事件传递机制
-----来源:http://www.trinea.cn/android/touch-event-delivery-mechanism/ 介绍Android Touch事件的传递机制. 不少朋友私信问 ...
- Android Touch事件传递机制具体解释 上
尊重原创:http://blog.csdn.net/yuanzeyao/article/details/37961997 近期总是遇到关于Android Touch事件的问题,如:滑动冲突的问题,曾经 ...
随机推荐
- [label][IDE] Develop Node.js Project With WebStorm
WebStorm 是一个支持 Node.js,CoffeeScript, TypeScript, Dart, Jade, Sass, LESS and Stylus 这些最新 web 开发技术的集成开 ...
- ERROR Function not available to this responsibility.Change responsibilities or contact your System Administrator.
APPLIES TO: Navigation: Help > Diagnostics > Custom Code > Personalize or Help > Diag ...
- s21day25 python笔记
s21day25 python笔记 正则表达式 1.定义 定义:正则表达式是一种规则匹配字符串的规则 re模块本身只是用来操作正则表达式的,和正则本身没关系 为什么要有正则表达式? 匹配字符串 一个人 ...
- Spring学习(五)——集成MyBatis
本篇我们将在上一篇http://www.cnblogs.com/wenjingu/p/3829209.html的Demo程序的基础上将 MyBatis 代码无缝地整合到 Spring 中. 数据库仍然 ...
- oracle 11gr2 2.04 em 更改 hostname 后无需重建资料库的方法
1) 备份删除$ORACKE_HOME/ xxxx-sid 的EM目录:复制要创建的xxx-sid EM 名称目录: 备份删除$ORACKE_HOME/oc4j/j2ee/ xxxx-sid 的EM目 ...
- Windows10 下 github ssh 访问出现 Permission denied(publickey)错误的解决方法
Windows10 下 github ssh 访问出现 Permission denied(publickey)错误的解决方法. 错误信息: git clone git@github.com:ediw ...
- WPF Image显示图片,文件被占用异常
imageControl.Source = this.GetBitmapImage(imagePath);//imageControl为WPF Image控件 public BitmapImage G ...
- UWP开发入门(三)——{x:Bind}扩展标记
上周打炉石打得太晚……忘记更新了,本周补上.本篇我们讲一下{x:Bind}扩展标记.{x:Bind}扩展标记也是Windows 10 Uinversal 新增的内容,按官方的说法是 {Binding} ...
- jquery点击页面其他位置隐藏div
$("#btnAdd").on('click', function (e) { $("#setUp").toggle(); $(document).one('c ...
- 为何会有Python学习计划
近几年感觉自己需要不断充电,从网上找寻技术潮流前端时Python映入眼帘,未来的技术,Python应该很有市场. 于是,以很低的成本从网上找到相关最新学习资料,希望自己未来的路,能坚持与书为伴,不断攀 ...