在Android中,消息的传递控制主要是通过两个方法共同配合使用来对用户的触摸消息进行分发的,下面就来看看这两个方法;

  1. onInterceptTouchEvent:此方法定义于ViewGroup中,顾名思义,这个方法是用于ViewGroup拦截(intercept)触摸消息的;
  2. 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;

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消息传递机制探究分析的更多相关文章

  1. Android异步消息传递机制源码分析

    1.Android异步消息传递机制有以下两个方式:(异步消息传递来解决线程通信问题) handler 和 AsyncTask 2.handler官方解释的用途: 1).定时任务:通过handler.p ...

  2. Android事件拦截机制简单分析

    前一阶段,在学习的时候,遇到了我觉得的我接触安卓以来的最多的一次事件拦截出来,那个项目,用到了slidemenu側滑菜单条,然后加上tab标签,还有轮播广告,listview上下滑动.viewpage ...

  3. 解析Android的 消息传递机制Handler

    1. 什么是Handler: Handler 网络释义"机械手.经理"意思,在Android它用于管理多个线程UI操作: 2. 为什么会出现Handler: 在Android里面的 ...

  4. Android touch mode和focusableInTouchMode分析

    首先我们来看看touch mode的定义.它是用户和手机进行交互时view层次结构的一个状态.它本身是很容易理解的, 代表了最近一次的交互是否是通过触摸屏发生的,因为在Android设备上还存在别的交 ...

  5. Android事件分发机制源代码分析

    小小感慨一下,做android有一段时间了,一直以来都是习惯整理笔记存到有道笔记上,没有写博客的习惯. 以后逐步分类整理出来,也算"复习"一遍了 - _ - . android的事 ...

  6. Android Handler消息传递机制

    在Android系统中,类Handler主要有如下两个作用. 在新启动的线程中发送消息. 在主线程中获取.处理消息. 类Handler在实现上述作用时,首先在新启动的线程中发送消息,然后在主线程中获取 ...

  7. Android学习笔记-事件处理之Handler消息传递机制

    内容摘要:Android Handler消息传递机制的学习总结.问题记录 Handler消息传递机制的目的: 1.实现线程间通信(如:Android平台只允许主线程(UI线程)修改Activity里的 ...

  8. Android事件传递机制详解及最新源码分析——ViewGroup篇

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 在上一篇<Android事件传递机制详解及最新源码分析--View篇>中,详细讲解了View事件的传递机制,没掌握或者掌握不扎实的小伙伴 ...

  9. Android Touch事件传递机制 二:单纯的(伪生命周期)

    转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...

随机推荐

  1. 理解Javascript的异步等待

    目前async / await特性并没有被添加到ES2016标准中,但不代表这些特性将来不会被加入到Javascript中.在我写这篇文章时,它已经到达第三版草案,并且正迅速的发展中.这些特性已经被I ...

  2. js图片时间翻转

    带素材 代码一: <!-- Author: XiaoWen Create a file: 2016-12-12 10:08:02 Last modified: 2016-12-12 11:30: ...

  3. 固定表头/锁定前几列的代码参考[JS篇]

    引语:做有难度的事情,才是成长最快的时候.前段时间,接了一个公司的稍微大点的项目,急着赶进度,本人又没有独立带过队,因此,把自己给搞懵逼了.总是没有多余的时间来做自己想做的事,而且,经常把工作带入生活 ...

  4. iOS-常用的辅助工具软件

    1.Navicat Premium11.0.20破解版快速安装配置(附文件)   Navicat Premium是当下非常好用的数据库管理软件,但是价格非常昂贵,并且还有某些小bug,感觉3000+的 ...

  5. wicket基础应用(3)——wicket控件的隐藏和显示

    在一个项目,页面经常要显示和隐藏一些控件,用wicket来控制显示和隐藏控件相当的方便. 1.最简单的隐藏和显示方法: wicket的控件大部分都有setVisible(...)方法,用这个方法就可以 ...

  6. Leetcode 65 Valid Number 字符串处理

    由于老是更新简单题,我已经醉了,所以今天直接上一道通过率最低的题. 题意:判断字符串是否是一个合法的数字 定义有符号的数字是(n),无符号的数字是(un),有符号的兼容无符号的 合法的数字只有下列几种 ...

  7. python函数的参数

    代码: # coding=utf8 # 可以传入任何个参数 def calc(*numbers): sum = 0 for n in numbers: sum = sum + n * n return ...

  8. Android ImageView的scaleType属性与adjustViewBounds属性(转载)

    ImageView的scaleType的属性有好几种,分别是matrix(默认).center.centerCrop.centerInside.fitCenter.fitEnd.fitStart.fi ...

  9. 最近碰到了一个病毒木马:virus.win32.ramnit.B

    由于 使用了 简单游 平台上的挂机工具: 番茄-自动人机对战免费版1217  ,使用了很久,头段时间家里电脑 360提示有病毒,本来我一直忽略的,但 我扫描了一下,大量的这个木马,于是 吧 简单游卸载 ...

  10. Javascript:常用函数封装

    //cookie function setCookie(name, value, iDay) { if(iDay!==false) { var oDate=new Date(); oDate.setD ...