Android的Touch事件处理机制比较复杂,特别是在考虑了多点触摸以及事件拦截之后。

Android的Touch事件处理分3个层面:Activity层,ViewGroup层,View层。

首先说一下Touch事件处理的几条基本规则。

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的处理方式)。

下面分层讲述一些细节。

1.Activity层:

public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) { //在这里交给View层处理
return true;
}
return onTouchEvent(ev); // 如果View层没有处理,则在这里处理
}

2.View层:

public boolean dispatchTouchEvent(MotionEvent event) {
// 省略了部分细节
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
return true;
}
if (onTouchEvent(event)) {
return true;
}
return false;
}

View的onTouch方法代码比较多,主要的逻辑分两步:先是将事件交给TouchDelegate处理(如果有的话),如果TouchDelegate没有处理再自行处理;自行处理主要负责View状态的变换(如按下状态),长按事件,点击事件的检测与触发等。

3.ViewGroup层(比较复杂):

ViewGroup层处理Touch事件的总体逻辑是:先检测是否需要拦截,没有拦截的话下发给子View处理,如果子View没有处理再自行处理,自行处理的逻辑与View一样。

拦截的逻辑是,将从down到up之间的所有事件看作一组事件,如果从down就拦截了,则组内的后续其它事件完全交给自己处理,不需要再进入拦截逻辑了;如果是从中间拦截,则先给子View发送cancel事件,组内的后续其它事件完全交给自己处理,不需要再进入拦截逻辑了。

分发的逻辑是,在ACTION_DOWN事件的时候,寻找子View进行处理,称为寻找Target;如果没有找到Target,则自行处理;如果找到Target,则交由Target处理。

从代码上看,dispatchTouchEvent负责分发逻辑,onTouchEvent负责真正的处理逻辑,一般应该重载onTouchEvent,只有特殊情况下才需要重载dispatchTouchEvent。

Android的Touch事件处理机制的更多相关文章

  1. Android平台的事件处理机制和手指滑动例子

    Android平台的事件处理机制有两种 基于回调机制的事件处理:Android平台中,每个View都有自己的处理事件的回调方法,开发人员可以通过重写View中的这些回调方法来实现需要的响应事件. 基于 ...

  2. Cocos2d-x Touch事件处理机制

    在Cocos2d-x中提供两种触摸事件处理机制:CCStandardTouchDelegate和CCTargetedTouchDelegate. 一.如何使用 0.默认情况下CCLayer都是没有启动 ...

  3. Cocos2d-x-3.0 Touch事件处理机制

    在学习Cocos2d-html5游戏例子的时候,注册事件代码一直提示:TypeError: cc.Director._getInstance(...).getTouchDispatcher is no ...

  4. Cocos2d-x之Touch事件处理机制

    一.两种机制的四种不同的事件 CCStandardTouchDelegate 默认事件   virtual void ccTouchesBegan(CCSet *pTouches, CCEvent * ...

  5. Android的事件处理机制(一)------基于回调机制的事件处理

    Android平台的事件处理机制有两种,一种是基于回调机制的,一种是基于监听接口的,现介绍第一种:基于回调机制的事件处理.Android平台中,每个View都有自己的处理事件的回调方法,开发人员可以通 ...

  6. Android基础新手教程——3.1 基于监听的事件处理机制

    Android基础新手教程--3.1.1 基于监听的事件处理机制 标签(空格分隔): Android基础新手教程 本节引言: 第二章我们学习的是Android的UI控件,我们能够利用这些控件构成一个精 ...

  7. Android菜鸟的成长笔记(11)——Android中的事件处理

    原文:[置顶] Android菜鸟的成长笔记(11)——Android中的事件处理 Android提供了两种方式来处理事件,一个是基于回调的事件处理,另一个是基于监听的事件处理,举个例子: 基于回调的 ...

  8. Android的两种事件处理机制

    UI编程通常都会伴随事件处理,Android也不例外,它提供了两种方式的事件处理:基于回调的事件处理和基于监听器的事件处理. 对于基于监听器的事件处理而言,主要就是为Android界面组件绑定特定的事 ...

  9. Android事件处理机制

    包括监听和回调两种机制. 1. 基于监听的事件处理: 事件监听包含三类对象,事件源,事件,事件监听器.Android的事件处理机制是一种委派式(Delegation)事件处理方式:普通组件(事件源)将 ...

随机推荐

  1. C++基础知识面试精选100题系列(21-30)[C++ basics]

    [本文链接] http://www.cnblogs.com/hellogiser/p/100-interview-questions-of-cplusplus-basics-21-30.html [题 ...

  2. ios 转发一篇对于6 plus的分辨率模式的说明

    http://segmentfault.com/q/1010000002545515 分为兼容模式和高分辨率模式. 兼容模式 当你的 app 没有提供 3x 的 LaunchImage 时,系统默认进 ...

  3. JAVA thread0.interrupt()方法

    interrupt()只是改变中断状态而已,interrupt()不会中断一个正在运行的线程.这一方法实际上完成的是,给受阻塞的线程抛出一个中断信号,这样受阻线程就得以退出阻塞的状态. 更确切的说,如 ...

  4. FIX_前缀后缀_未提交

    问题 B: FIX 时间限制: 1 Sec  内存限制: 64 MB提交: 38  解决: 11[提交][状态][讨论版] 题目描述 如果单词 X 由单词 Y 的前若干个字母构成,我们称 X 是 Y ...

  5. HDU 2602 Bone Collector WA谁来帮忙找找错

    Problem Description Many years ago , in Teddy’s hometown there was a man who was called “Bone Collec ...

  6. codevs 3290 华容道(SPFA+bfs)

    codevs 3290华容道 3290 华容道 2013年NOIP全国联赛提高组 时间限制: 1 s  空间限制: 128000 KB 题目描述 Description 小 B 最近迷上了华容道,可是 ...

  7. 在JAVA中如何跳出当前的多重嵌套循环

    可以使用return,但使用return后,会跳出整个函数,多重循环后面的代码无法执行. public static void main(String[] args) { // TODO Auto-g ...

  8. 常用js函数整理--common.js

    var h = {}; h.get = function (url, data, ok, error) { $.ajax({ url: url, data: data, dataType: 'json ...

  9. js对象

    js中除数字.字符串.布尔值.null值.undefined之外都是对象. 对象是属性的容器,属性包含属性名和值,属性名可以是包括空字符串在内的任意字符串(个人想法还是使用js标识符好,省的麻烦),值 ...

  10. orcad 元件库的查找位置对照表

    orcad元件库的查找: 如下:1.原理图常用库文件: MiscellaneousDevices.ddb: DallasMicroprocessor.ddb: IntelDatabooks.ddb: ...