MotionEvent源代码可以在ocs看到,当然你也可以在SDK中下载源代码,或者其他地方,如:

https://github.com/CyanogenMod/android_frameworks_base/blob/ics/core/java/android/view/MotionEvent.java

(1)首先是MotionEvent 中getAction()与getActionMasked()的区别:

首先看代码:

01     /**
02      * Bit mask of the parts of the action code that are the action itself.
03      */
04     public static final int ACTION_MASK             = 0xff;
05  
06 /**
07      * Return the kind of action being performed.
08      * Consider using {<a href="http://my.oschina.net/link1212" target="_blank" rel="nofollow">@link</a> #getActionMasked} and {<a href="http://my.oschina.net/link1212" target="_blank" rel="nofollow">@link</a> #getActionIndex} to retrieve
09      * the separate masked action and pointer index.
10      * @return The action, such as {<a href="http://my.oschina.net/link1212" target="_blank" rel="nofollow">@link</a> #ACTION_DOWN} or
11      * the combination of {<a href="http://my.oschina.net/link1212" target="_blank" rel="nofollow">@link</a> #ACTION_POINTER_DOWN} with a shifted pointer index.
12      */
13     public final int getAction() {
14         return mAction;
15     }
16  
17   /**
18      * Return the masked action being performed, without pointer index information.
19      * Use {<a href="http://my.oschina.net/link1212" target="_blank" rel="nofollow">@link</a> #getActionIndex} to return the index associated with pointer actions.
20      * @return The action, such as {<a href="http://my.oschina.net/link1212" target="_blank" rel="nofollow">@link</a> #ACTION_DOWN} or {<a href="http://my.oschina.net/link1212" target="_blank" rel="nofollow">@link</a> #ACTION_POINTER_DOWN}.
21      */
22     public final int getActionMasked() {
23         return mAction & ACTION_MASK;
24     }

上面的代码是基于android2.2的,注释是android4.X中最新的.

他们有什么区别呢?如果mAction的值是在0x00到0xff之间的话。getAction()返回的值,和

getActionMasked()的返回的值是一样的。

(Q1)那什么时候返回的值是一样的呢?即当mAction值大于0xff时,那什么时候会大于0xff呢?

这就是是当有多点触控时。当有多点触控时。

mAction的低8位即0x00到0xff用来表示动作的类型信息。

例如:MotionEvent#ACTION_DOWN的值是 0,即0x00。

MotionEvent#ACTION_UP的值是 1,即0x01。

等等。

但是,我们知道Android是支持多点触控的,那么怎么知道这个一个MotionEvent是哪一个

触控点触发的呢?那么就还需要MotionEvent带有触控点索引信息。

Android的解决方案时在;mAction的第二个8位中存储。

例如,如果mAction的值是0x0000,则表示是第一个触控点的ACTION_DOWN操作。

如果mAction的值是0x0100呢,则表示是第二个触控点的ACTION_DOWN操作。

第三个的ACTION_DOWN呢?相信你可以推出来是0x0200。

总而言之,mAction时的低8位(也就是0-7位)是动作类型信息。

mAction的8-15位呢,是触控点的索引信息。(即表示是哪一个触控点的事件)。

(Q2),为什么不用两个字段来表示。

如   int mAction,int mPointer,

mAction表示动作类型,mPointer表示第几个触控点。

因为,动作类型只要0-255就可以了,动作类型,mPointer也是。

只要一个字段(32位),否则需要两个字段(32*2=64位),即可以节约内存。又可以方便提高处理速度。

不过通常我们都是以不同的字段来存储不同的信息。但是在计算机内部他们还是变成了0,1。

计算机始终还是以位来存储信息的。如果我们多我熟悉以位为基本单位来理解信息的存储。对于理解android中的很多变量是很有帮助的。因为他其中的很多东西使用的这样的节约内在的技巧。

如onMeasure中的MeasureSpec。

=================== the above is update at 2013-01-24=====

先看关于这两个方法注释:

我简单的翻译如下:

01 /**
02      * action码的位掩码部分就是action本身
03      */
04     public static final int ACTION_MASK             = 0xff;
05  
06 /**
07   返回action的类型,考虑使用getActionMasked()和getActionIndex()来获得单独的经过掩码的action和触控点的索引.
08  @return action例如ACTION_DOWN或者ACTION_POINTER_DOWN与转换的触控点索引的合成值
09      */
10     public final int getAction() {
11         return mAction;
12     }
13  
14   /**
15    返回经过掩码的action,没有触控点索引信息.
16    通过getActionIndex()来得到触控操作点的索引.
17 @return action,例如ACTION_DOWN,ACTION_POINTER_DOWN
18  
19   
20      */
21     public final int getActionMasked() {
22         return mAction & ACTION_MASK;
23     }

在上面的两个方法中注释出现差异的地方是对于ACTION_POINTER_DOWN的描述:

通过getAction()返回的ACTION_POINTER_DOWN的是与转换触控点索引的合成值.

而getActionMasked()则就是一个ACTION_POINTER_DOWN的值:

这么来看我们知道一个action的代码值还包含了action是那个触控点的索引值:

现在我们对比来看看ACTION_MASK和ACTION_POINTER_INDEX_MASK

1 public static final int ACTION_MASK             = 0xff;
2 public static final int ACTION_POINTER_INDEX_MASK  = 0xff00;

还没有看出来什么吗?

您把ACTION_MASK看成是0x00ff

就知道了吧.

也就是说,一个MotionEvent中的action代码,

前8位是实实在在包含表示哪一个动作常量.

后八位呢就是包含了触控点的索引信息.

因为ACTION_MASK = 0x00ff所以,经过ACTION_MASK掩码过后的action码就没有索引信息了.

如何得索引值呢?

原理:

先将action跟0xff00相与清除前8位用于存储动作常量的信息,

然后将action右移8位就可以得到索引值了.

我们就可以自己想办法得到索引信息了.

即先对action用ACTION_POINTER_INDEX_MASK进行掩码处理,

即  maskedIndex = action&ACTION_POINTER_INDEX_MASK = action&0xff00

这各掩码也就是将action这个数的前8位清零.

然后再将maskedIndex向右移8位就能够得到索引值了.

再看看android真实是怎么做的吧,

用于右移8位的常量.

1 /**
2    * Bit shift for the action bits holding the pointer index as
3    * defined by {<a href="http://my.oschina.net/link1212" target="_blank" rel="nofollow">@link</a> #ACTION_POINTER_INDEX_MASK}.
4    */
5   public static final int ACTION_POINTER_INDEX_SHIFT = 8;

再年得到索引值方法源代码,如下:

1 public final int getActionIndex() {
2     return (mAction & ACTION_POINTER_INDEX_MASK) >> ACTION_POINTER_INDEX_SHIFT;
3 }

为什么要有索引信息?

 因为,这样说吧,android中,当有触摸事件发生时(假设已经注册了事件监听器),调用你注册监听器中的方法onTouch(,MotionEvent ev);传递了一个MotionEvent的对象过来.

但是,想想,上面只传递进来一个MotionEvent过来,如果只是单点触控那是没有问题.

问题就是当你多个手指触控的时候也是只传递这一个MotionEvent进来,

这个时候,你当然想知道每个手指的所对应的触控点数据信息啦.

所以MotionEvent中有就要索引信息了.

事件是你可以很容易通过API看到,MotionEvent还包含了移动操作中其它历史移动数据.

方便处理触控的移动操作.

android sdk对于这个类的描述中就有这么一句:

For efficiency, motion events with ACTION_MOVE may batch together multiple movement samples within a single object.

我翻译下:"出于效率的考虑,事件代码为ACTION_MOVE的Motion,会在一个MotionEvent对象中包含多个移动数据采样."

现在我们对于MotionEvent有了初步的了解了.

PS:

我发现android4中MotionEvent中的代码大多变成了原生代码了:

例如如getX(int)在2.2中是这样的:

1 public final float getX(int pointerIndex) {
2     return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_X];
3 }

但到了4.x是这样的了:

1 public final float getX(int pointerIndex) {
2      return nativeGetAxisValue(mNativePtr, AXIS_X, pointerIndex, HISTORY_CURRENT);
3  }

android触控,先了解MotionEvent的更多相关文章

  1. android触控,先了解MotionEvent(一)

    http://my.oschina.net/banxi/blog/56421 这是我个人的看法,要学好android触控,了解MotionEvent是必要,对所用的MotionEvent常用的API要 ...

  2. Android触控屏幕Gesture(GestureDetector和SimpleOnGestureListener的使用教程)

    1.当用户触摸屏幕的时候,会产生许多手势,例如down,up,scroll,filing等等,我们知道View类有个View.OnTouchListener内部接口,通过重写他的onTouch(Vie ...

  3. Android触控屏幕Gesture(GestureDetector和SimpleOnGestureListener的使用教程) 分类:Androidandroid实例

    1.当用户触摸屏幕的时候,会产生许多手势,例如down,up,scroll,filing等等,我们知道View类有个View.OnTouchListener内部接口,通过重写他的onTouch(Vie ...

  4. Android触碰事件

    OnTouchListener使用 public class ViewActivity extends Activity implements View.OnTouchListener { @Over ...

  5. Android 多点触控与简单手势(一)

    现在一般的Android手机都会使用电容触摸屏最少可以支持两点触摸,多的可能是七八个,所以基本上都会支持多点触控, android系统中应用程序可以使用多点触控的事件来完成各种手势和场景需求. And ...

  6. Android多点触控技术

    1 简介 Android多点触控在本质上需要LCD驱动和程序本身设计上支持,目前市面上HTC.Motorola和Samsung等知名厂商只要使用电容屏触控原理的手机均可以支持多点触控Multitouc ...

  7. 安卓Tv开发(一)移动智能电视之焦点控制(触控事件)

    前言:移动智能设备的发展,推动了安卓另一个领域,包括智能电视和智能家居,以及可穿戴设备的大量使用,但是这些设备上的开发并不是和传统手机开发一样,特别是焦点控制和用户操作体验风格上有很大的区别,本系列博 ...

  8. 【朝花夕拾】Android自定义View篇之(八)多点触控(上)MotionEvent简介

    前言 在前面的文章中,介绍了不少触摸相关的知识,但都是基于单点触控的,即一次只用一根手指.但是在实际使用App中,常常是多根手指同时操作,这就需要用到多点触控相关的知识了.多点触控是在Android2 ...

  9. cocos2d3.x在android下屏蔽多点触控

    ios上很简单的在AppController.mm里 [eaglView setMultipleTouchEnabled:YES] 设置为NO,就是单点触控了,无需更改cocos底层代码; andro ...

随机推荐

  1. Express中间件

    一.编写中间件 中间件函数能够访问请求对象(req),响应对象(res),应用程序的请求/响应循环中的下一个中间件函数.下一个中间件函数通常由名为next的变量来表示. 中间件函数可以执行以下任务: ...

  2. hdoj 5199 Gunner map

    Gunner Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5199 D ...

  3. 小程序navigator点击有时候会闪一下

    <navigator hover-class="none">

  4. ASP.NET Web API教程 分页查询

    首先增加支持分页的API方法 public IEnumerable<UserInfo> GetUserInfos(int pageindex, int size)         {    ...

  5. poj 1028 Web Navigation(模拟)

    题目链接:http://poj.org/problem? id=1028 Description Standard web browsers contain features to move back ...

  6. .Net高级技术——对象序列化

    对象序列化 “序列化是将一个对象保存到存储介质上或者将对象进行转换使之能够在网络上传送的行为”.通俗一点的解释,序列化就是把一个对象保存到一个文件或数据库字段中去,反序列化就是从文件或者数据库中取出数 ...

  7. C#引用类型转换的几种方式

    本篇体验引用类型转换:子类转换成父类,父类转换成子类,以及不是子父级关系类之间的转换. □ 隐式转换:子类转换成父类 public class Animal { public int _age; pu ...

  8. HTTP 协议中 Vary 的一些研究

    经常抓包看 HTTP 请求的同学应该对 Vary 这个响应头字段并不陌生,它有什么用?用 PageSpeed 工具检查页面时,经常看到「Specify a Vary: Accept-Encoding ...

  9. C#编程(五)----流程控制

    流控制(控制语句) 程序的代码不是按照从上往下执行的,是按照控制语句执行的. 条件语句 C#中有两个控制语句:if语句还有switch语句 1.if语句   C#中继承了C和C++中的if语句,语法直 ...

  10. Oracle中Instr用法

    在项目中用到了Oracle中 Instr 这个函数,顺便仔细的再次学习了一下这个知识. Oracle中,可以使用 Instr 函数对某个字符串进行判断,判断其是否含有指定的字符. 其语法为:Instr ...