这是我个人的看法,要学好android触控,了解MotionEvent是必要,对所用的MotionEvent常用的API要比较深入的了解.
下面是我个人的学习过程记录:
MotionEvent源代码可以在ocs看到,当然你也可以在SDK中下载源代码,或者其他地方,如:
(1)首先是MotionEvent 中getAction()与getActionMasked()的区别:
他们有什么区别呢?如果mAction的值是在0x00到0xff之间的话。getAction()返回的值,和getActionMasked()的返回的值是一样的。
(Q1)那什么时候返回的值是一样的呢?即当mAction值大于0xff时,那什么时候会大于0xff呢?
Android的解决方案是:在mAction的第二个8位中存储。
例如,如果mAction的值是0x0000,则表示是第一个触控点的ACTION_DOWN操作。
总而言之,mAction时的低8位(也就是0-7位)是动作类型信息。
(Q2),为什么不用两个字段来表示。
如
mAction表示动作类型,mPointer表示第几个触控点。
因为,动作类型只要0-255就可以了,动作类型,mPointer也是。
只要一个字段(32位),否则需要两个字段(32*2=64位),即可以节约内存。又可以方便提高处理速度。
不过通常我们都是以不同的字段来存储不同的信息。但是在计算机内部他们还是变成了0,1。
如onMeasure中的MeasureSpec。
先看关于这两个方法注释:
我简单的翻译如下:
在上面的两个方法中注释出现差异的地方是对于ACTION_POINTER_DOWN的描述: 通过getAction()返回的ACTION_POINTER_DOWN的是与转换触控点索引的合成值.
这么来看我们知道一个action的代码值还包含了action是那个触控点的索引值: 现在我们对比来看看ACTION_MASK和ACTION_POINTER_INDEX_MASK
您把ACTION_MASK看成是0x00ff
如何得索引值呢?
原理:
先将action跟0xff00相与,清除前8位(0-7位)用于存储动作常量的信息,然后将action右移8位就可以得到索引值了.
我们就可以自己想办法得到索引信息了.
即先对action用ACTION_POINTER_INDEX_MASK进行掩码处理,
即
这个掩码也就是将action这个数的前8位清零.
然后再将maskedIndex向右移8位就能够得到索引值了.
再看看android真实是怎么做的吧,
用于右移8位的常量.
1 | public final int getActionIndex() { |
2 | return (mAction & ACTION_POINTER_INDEX_MASK) >> ACTION_POINTER_INDEX_SHIFT; |
3 | } |
为什么要有索引信息?
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中的代码大多变成了原生代码了: