Android Touch消息传递机制探究分析

在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形态;

时间: 2024-08-26 13:59:52

Android Touch消息传递机制探究分析的相关文章

Android异步消息传递机制源码分析&&相关知识常被问的面试题

1.Android异步消息传递机制有以下两个方式:(异步消息传递来解决线程通信问题) handler 和 AsyncTask 2.handler官方解释的用途: 1).定时任务:通过handler.postDelay(Runnable r, time)来在指定时间执行msg. 2).线程间通信:在执行较为耗时操作的时候,在子线程中执行耗时任务,然后handler(主线程的)把执行的结果通过sendmessage的方式发送给UI线程去执行用于更新UI. 3.handler源码分析 一.在Activ

android线程消息传递机制——Looper,Handler,Message

android线程消息传递机制——Looper,Handler,Message 在引入这些概念之前,我们先了解一下引入这些机制的背景. 出于性能优化的考虑,Android的UI操作并不是线程安全的(如果你不懂什么是线程安全,可以阅读一下<一起探究多进程与多线程>里的数据安全与可重入),这意味着如果有多个线程同时操作某个UI组件,可能导致线程安全问题.为了解决这个问题,Android制定了一条简单的规则:只允许UI线程修改Activity里的UI组件.这个UI线程也通常被我们称为主线程. 在此引

解析Android的 消息传递机制Handler

1. 什么是Handler: Handler 网络释义"操纵者,管理者的"意思,在Android里面用于管理多线程对UI的操作: 2. 为什么会出现Handler: 在Android的设计机制里面,只允许主线程(一个程序第一次启动时所移动的线程,因为此线程主要是完成对UI相关事件的处理,所以也称UI线程) 对UI进行修改等操作,这是一种规则的简化,之所以这样简化是因为Android的UI操作时线程不安全的,为了避免多个线程同时操作UI造成线程安全 问题,才出现了这个简化的规则. 由此以

Android Handler消息传递机制

1. Handler消息传递机制初步认识:什么是Handler? handler通俗一点讲就是用来在各个线程之间发送数据的处理对象.在任何线程中,只要获得了另一个线程的handler,则可以通过 handler.sendMessage(message)方法向那个线程发送数据.基于这个机制,我们在处理多线程的时候可以新建一个thread,这个thread拥有UI线程中的一个handler.当thread处理完一些耗时的操作后通过传递过来的handler向UI线程发送数据,由UI线程去更新界面. 主

Android Handler消息传递机制详解

1.为什么要用Handler 出于性能优化的考虑,Android UI操作并不是线程安全,如果有多个线程并发操作UI组件,可能导致线程安全问题.可以设想下,如果在一个Activity中有多个线程去更新UI,并且都没有加锁机制,可能会导致什么问题? 界面混乱,如果加锁的话可以避免该问题但又会导致性能下降.因此,Android规定只允许UI线程修改Activity的UI组件.当程序第一次启动时,Android会同时启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,比如用户

Android touch mode和focusableInTouchMode分析

转载自http://www.cnblogs.com/xiaoweiz/p/3833079.html 首先我们来看看touch mode的定义.它是用户和手机进行交互时view层次结构的一个状态.它本身是很容易理解的, 代表了最近一次的交互是否是通过触摸屏发生的,因为在Android设备上还存在别的交互方式,比如D-pad.滚动球等等. 为什么Android会引入这样一个mode呢?这是因为从交互.设计方面考虑,当用户直接使用keys或trackball与UI 进行交互的时候,必须先使目标控件获得

掌握Android Touch事件机制

DaveSmith @devunwired 要点涵盖 l  Touch系统概述 l  Framwork层的Touch事件 l  Touch事件的处理 l  系统提供的TouchHandlers l  系统提供的GestureHandlers Android系统怎么处理Touch事件? l  每一个touch事件都被封装成一个MotionEvent对象 l  这个对象描述了用户当前的动作 – ACTION_DOWN – ACTION_UP – ACTION_MOVE –ACTION_POINTER

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

小小感慨一下,做android有一段时间了,一直以来都是习惯整理笔记存到有道笔记上,没有写博客的习惯. 以后逐步分类整理出来,也算"复习"一遍了 - _ - . android的事件分发相关的方法有三个: 1.public booleandispatchTouchEvent(MotionEvent ev) 2.public boolean onInterceptTouchEvent(MotionEvent ev) 3.public booleanonTouchEvent(MotionE

Android中资源管理机制详细分析

尊重原创:http://blog.csdn.net/yuanzeyao/article/details/42386549 在Android中,所有的资源都在res目录下存放,包括drawable,layout,strings,anim等等,当我们向工程中加入任何一个资源时,会在R类中相应会为该 资源分配一个id,我们在应用中就是通过这个id来访问资源的,相信做过Andorid开发的朋友对于这些肯定不会陌生,所以这个也不是我今天想要说的,我今天想和大家一起学习的是Android是如何管理资源的,在