Android Touch消息传递机制探究分析
在Android中,消息的传递控制主要是通过两个方法共同配合使用来对用户的触摸消息进行分发的,下面就来看看这两个方法;
- onInterceptTouchEvent:此方法定义于ViewGroup中,顾名思义,这个方法是用于ViewGroup拦截(intercept)触摸消息的;
- onTouchEvent:此方法定义于View中,用于处理用户的触摸事件;
下面来看这两个方法的定义原型;
public boolean onInterceptTouchEvent(MotionEvent ev);
public boolean onTouchEvent(MotionEvent event);
这两个方法的一个共同点就是都有一个参数MotionEvent用于获取触摸事件的具体信息(比如按下,移动等等消息形态)和函数返回值(用于控制不同场合的触摸处理);
简单说一下MotionEvent,它包含了用户触摸消息的类型,常用的几种触摸消息类型为:ACTION_DOWN,ACTION_MOVE,ACTION_UP,ACTION_CANCEL, 分别表示触摸按下,移动,结束的状态;这几种消息类型不是并发产生的,而是如同触摸发生的次序一样有序产生的,DOWN->MOVE->UP/CANCEL;
下边通过一个例子来研究,分别自定义一个简单的ViewGroup和View,用于跟踪onTouchEvent和onInterceptTouchEvent的执行;
LLinearLayout
public class LLinearLayout extends LinearLayout {
public LLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LLinearLayout(Context context) {
super(context);
}
private float lastY;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
String tag = "onInterceptTouchEvent";
Log.w(tag, "" + super.onInterceptTouchEvent(ev));
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.w(tag, "ACTION_DOWN");
lastY = ev.getX();
break;
case MotionEvent.ACTION_MOVE:
Log.w(tag, "ACTION_MOVE");
if (ev.getX() - lastY > 20) {
Log.w(tag, "ACTION_MOVE>20");
return true;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
Log.w(tag, "ACTION_UP");
break;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.w("onTouchEvent", "" + super.onTouchEvent(event));
return false;
}
}
LView
public class LView extends ImageView {
public LView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LView(Context context) {
super(context);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
String tag = "LView.onTouchEvent";
Log.e(tag, "" + super.onTouchEvent(event));
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(tag, "ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(tag, "ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
Log.e(tag, "ACTION_UP");
break;
}
return false;
}
}
在xml文件中将LView加入LLinearLayout中,通过一系列更改来一控究竟;
step1:

通过上面的Log信息,可以看出,触摸事件先被LLinearLayout拦截到(onInterceptTouchEvent),在这个Demo中,该方法返回值为false,接着就将Touch事件传递给LView,LView的onTouchEvent响应了此次触摸事件,并且也返回false;然后Touch事件再传递给LLinearLayout的onTouchEvent进行处理;
从上面我们可以简单的看出,Touch事件先被LLinearLayout拦截到,然后传递给LView,LView执行onTouchEvent处理逻辑;然后LLinearLayout再执行自己的onTouchEvent处理逻辑;@1
step2:将上面LLinearLayout的onInterceptTouchEvent方法返回值改为true,再次运行程序;

相比上面的Log信息,可以看到消息没有传递到LView;到这里,应该可以得出一个小小的结论了吧;
ViewGroup里面的onInterceptTouchEvent返回值,返回true表示拦截Touch事件,不再将Touch事件传递给ViewGroup里面的子View;
WVPJ6SJ[D]}DW)9AJNJCP.jpg)
step3: 回到step1,将LView中onTouchEvent返回值改为true,再次运行程序,手指从屏幕右滑到左;

从Log信息中,可以看出,LView的onTouchEvent返回值为true时,LView的触摸事件从DOWN传递到了MOVE,再传递到UP;当然,整个过程都是先由LLinearLayout的onInterceptTouchEvent先接收到Touch事件,在这里,并没有拦截Touch事件,而是将Touch事件传递给子View;细心的朋友可能会发现,在这里,并没有执行到LLinearLayout的onTouchEvent方法,why?其实是因为LView的onTouchEvent事件返回了true,表示处理消耗了此事件,不再继续传递,也就不执行到LLinearLayout的onTouchEvent方法;
结论:View的onTouchEvent返回值表示是否将继续传递Touch事件,比如如果返回true,触摸形态将会从DOWN传递到MOVE再到UP(这里这个说法其实不严谨,这里指的是整个onTouchEvent方法返回值都是true,而没有分段返回,比如在MOVE形态时返回了false);
step4:继续step3,运行程序,手指从屏幕左滑到右;

在LLinearLayout的onInterceptTouchEvent中,如果MOVE消息向右滑动距离大于20,则将拦截Touch事件,所以,在事件被拦截后,将不会再像step3中,MOVE消息会在LView的onTouchEvent中不断传递,而是被中断,触摸形态变为到ACTION_UP即手指抬起(其实这里这样说是不对的,准确的说是触摸形态变为ACTION_CANCEL,因为我将UP和CANCEL处理为一类,所以如上图,打印出来的Log信息为ACTION_UP,实际上它本质是ACTION_CANCEL);然后由于ACTION_MOVE被拦截,所以在手指MOVE的时候LLinearLayout的onTouchEevent不断被调用;
结尾总结:
ViewGroup里的onInterceptTouchEvent默认值是false,只有当返回值是false的时候,Touch事件才传给子View,然后调用到子View的onTouchEvent;返回值为true的时候,将拦截用户Touch事件,子View则捕获不到触摸事件;
View的onTouchEvent方法,当返回值为true的时候,事件将继续往下传递,由ACTION_DOWN传递到ACTION_MOVE再到ACTION_UP,反之如果返回值为false,则只会捕获到MotionEvent的ACTION_DOWN形态;
Android Touch消息传递机制探究分析的更多相关文章
- Android异步消息传递机制源码分析
1.Android异步消息传递机制有以下两个方式:(异步消息传递来解决线程通信问题) handler 和 AsyncTask 2.handler官方解释的用途: 1).定时任务:通过handler.p ...
- Android事件拦截机制简单分析
前一阶段,在学习的时候,遇到了我觉得的我接触安卓以来的最多的一次事件拦截出来,那个项目,用到了slidemenu側滑菜单条,然后加上tab标签,还有轮播广告,listview上下滑动.viewpage ...
- 解析Android的 消息传递机制Handler
1. 什么是Handler: Handler 网络释义"机械手.经理"意思,在Android它用于管理多个线程UI操作: 2. 为什么会出现Handler: 在Android里面的 ...
- Android touch mode和focusableInTouchMode分析
首先我们来看看touch mode的定义.它是用户和手机进行交互时view层次结构的一个状态.它本身是很容易理解的, 代表了最近一次的交互是否是通过触摸屏发生的,因为在Android设备上还存在别的交 ...
- Android事件分发机制源代码分析
小小感慨一下,做android有一段时间了,一直以来都是习惯整理笔记存到有道笔记上,没有写博客的习惯. 以后逐步分类整理出来,也算"复习"一遍了 - _ - . android的事 ...
- Android Handler消息传递机制
在Android系统中,类Handler主要有如下两个作用. 在新启动的线程中发送消息. 在主线程中获取.处理消息. 类Handler在实现上述作用时,首先在新启动的线程中发送消息,然后在主线程中获取 ...
- Android学习笔记-事件处理之Handler消息传递机制
内容摘要:Android Handler消息传递机制的学习总结.问题记录 Handler消息传递机制的目的: 1.实现线程间通信(如:Android平台只允许主线程(UI线程)修改Activity里的 ...
- Android事件传递机制详解及最新源码分析——ViewGroup篇
版权声明:本文出自汪磊的博客,转载请务必注明出处. 在上一篇<Android事件传递机制详解及最新源码分析--View篇>中,详细讲解了View事件的传递机制,没掌握或者掌握不扎实的小伙伴 ...
- Android Touch事件传递机制 二:单纯的(伪生命周期)
转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...
随机推荐
- [游戏模版21] Win32 物理引擎 能量守恒
>_<:Only a little change in the function of MyPaint(...),besides the initial value have some c ...
- [Java Web] 1、Web开发初识——一大堆历史和技术名词
LZ前言 LZ最近发现网络真是个神奇的东西,以前做的好玩的只能自娱自乐(或者说顾影自怜),现在只要发一个帖子,写一个博客,很快能引来一大群小伙伴的围观(有时候还能遇见几个大牛给个战略性的指导)...L ...
- 小米Web前端JavaScript面试题
面试题目 一. 请定义这样一个函数 function repeat (func, times, wait) { } 这个函数能返回一个新函数,比如这样用 var repeatedFun = repea ...
- bundle与package区别与联系
转:http://blog.csdn.net/lmbda/article/details/17895619 bundle是Apple提供的软件安装的便捷方法. bundle为用户和开发者提供了一个简单 ...
- Quartz 框架的应用
本文将简单介绍在没有 Spring 的时候..如何来使用 Quartz... 这里跳过 Quartz 的其他介绍.如果想更加输入的了解 Quartz,大家可以点击下载Quartz的帮助文档. Quar ...
- vs2012 MSDN帮助文档离线包下载安装方法
vs2012安装文件 自带的 MSDN帮助文档不全, 需要自己手动添加需要的离线文档包, 具体方法如下 1. 打开 vs2012 2. 按 ctrl + alt + F1 打开帮助文档管理器 3. 在 ...
- 使用Reveal查看任意App的技巧
转:http://www.jianshu.com/p/4dc8f94ca27c 前言 Reveal(http://revealapp.com)是一个很强大的iOS View Hierarchy工具,与 ...
- c#之第一课入门
这几天看到微软的build大会,感觉微软不甘落后他人,曾经的巨头难道又要重新崛起,不管了,为了以后的饭碗,还是简单学习一些c#吧,有时这种紧张感不错的,现在由于这种紧张感,我已经掌握的java(主要弄 ...
- Jquery EasyUI封装简化操作
//confirm function Confirm(msg, control) { $.messager.confirm('确认', msg, function (r) { if (r) { eva ...
- 使用 dbms_xplan.display 按照 plan_hash_value 查执行计划的方法
dbms_xplan.display_* 能按照 plan_hash_value 只有 display_awr 方法,如果这个SQL PLAN 刚刚生成,没有写入到AWR怎么办呢? 可以将 V$SQL ...