关于 MotionEvent 的笔记
2016-05-05 20:36
633 查看
概述
MotionEvent 不仅仅用来表示 触摸事件, 还可以是 鼠标/trackball/pen 等等事件.一个MotionEvent包含的信息: ACTION_DOWN 这种, 坐标, 压力, 大小, 方向.
两个相邻的 MotionEvent 的 时间间隔差不多是 10–40 ms 之间.
即, 这个时间段 其实也够了;
即 每秒种保证了 25—100 次的刷新, 即使ui上的更新, 也感觉比较顺滑的了.
关于pointerId和pointerIndex
每一个MotionEvent 都 包含了 当前所有 触摸点(Pointer)的信息—-即使它没有动.即如果有多个手指在屏幕上面, 即使只有一个手指动, 但是这个MotionEvent中包含了所有的pointer的信息(坐标/压力等).
有两个不同的东西:
pointerId
在一个pointer的down到up之间, 其值恒定;
其值可能会大于 pointers的总数;
因为中途可能会有pointer离开, 其对应的pointerId就空了(当然可能会被新down下去的pointer拿去用);
pointerId失效后, 可能会被新down下去的pointer拿去用.
pointerIndex
一个pointer在down到up之间时, 其pointerIndex值是可能会有变化的.
比如, 总共有4个pointers.
一个pointer的pointerIndex为3,
但此时pointerIndex为1的手指up了, 那么总共变成了3个pointers了,
此时这个pointer的pointerIndex可能就会被调整为2了.
关于pointerId
每一个触摸点 都有一个 pointerid—-这个是唯一的, 一直有效的.(但在up/pointer_up后会失效, 可能会别新按下去的手指拿去)
获取 pointerId 的办法:
int getPointerId(int pointerIndex)//参数是0什么的, 最大为: int getPointerCount()-1 ----注意, 在每一个gesture中, 一个手指的 pointerIndex 可能会不同, 但在 pointerId 却是一样的. 一个 pointerId 的有效期: 从这个手指 down/pointer_down 到 up/pointer_up 这一段时间之内. 注意: pointerId 也是按 0,1,2,3...之类的序号排下去的. 一个手指的pointerId 在 up/pointer_up 后就无效了, 其可能会被 其它新 按下去的 手指拿去用. ----这个要注意! ----即 pointerId 并非在 一个gesture 中一直唯一表明某一个手指的, 而仅仅是指 一个手指down/pointer_down 到 up/pointer_up 这一段时间之内 的id值.
关于pointerIndex
pointerIndex 则是从0–getPointerCount() 之间;
一个 pointer 的 index 其 会随着 情况的变化而变化, —-即不恒定.
比如,
总共有4个pointers.
一个pointer的pointerIndex为3,
但此时pointerIndex为1的手指up了, 那么总共变成了3个pointers了,
此时这个pointer的pointerIndex可能就会被调整为2了.
以下这些方法的参数用的都是 pointerIndex, 而不是 pointer id:
getX(int), getY(int), getAxisValue(int), getPointerId(int), //参数是pointerIndex, 返回的是 pointerId getToolType(int)
关于 pointerIndex 和 pointerId 之间的转换:
方法: getPointerId(int) , 我们通过 pointer index 来得到这个 pointer的id
方法: findPointerIndex(int) , 我们可以 通过 pointer id 得到 其 index.
列几个重要的方法吧(有些前面已列过了)
如下:int getPointerCount() int getPointerId(int pointerIndex) int findPointerIndex(int pointerId) int getPointerId(int pointerIndex) int getPointerIdBits() 这个方法是, 拿到当前这个MotionEvent的所有手指的id号.----这些id号 按位运算 放到 一个 int数据中. 比如, 有3个手指, 其对应的id为 2,3,5, 则返回的是 0000 0000 0010 1100, 即, 0x2c了. ----注意的是 pointerId 其实很朴素, 就是0, 1, 2, 3.....之类排下去的.
关于 Action 和 ActionMask 和 ActionIndex:
关于Action的简述:内部用于标注事件类型的方式是:—-有一个int型数据用于记录 一个pointer的pointerIndex和action.
低版本直接做为MotionEvent的数据成员:
private int mAction;
高版本MotionEvent中需要通过jni来查询:
private static native int nativeGetAction(long nativePtr)
这个 int 型数据 实现上只用到了 低两位, 比如:
0x0101 ---- 高8位, 表示 pointerIndex 低8位, 表示 事件类型, ACTION_DOWN/ACTION_UP/ACTION_POINTER_DOWN 之类.
相关几个方法:
int getAction() 返回的 0x0101 这种. int getActionMasked() 返回的是 低8位, 即 事件类型, ACTION_DOWN/ACTION_UP/ACTION_POINTER_DOWN 之类. int getActionIndex() 返回的是 高8位, 即pointerIndex. 发生了 ACTION_POINTER_DOWN 和 ACTION_POINTER_UP 的 pointer 的 index.
内部标识位 的 详解:
action 类型:
public static final int ACTION_MASK = 0xff; //用于获取低8位. public static final int ACTION_DOWN = 0; public static final int ACTION_UP = 1; public static final int ACTION_MOVE = 2; public static final int ACTION_CANCEL = 3; public static final int ACTION_OUTSIDE = 4; public static final int ACTION_POINTER_DOWN = 5; public static final int ACTION_POINTER_UP = 6; public static final int ACTION_HOVER_MOVE = 7; public static final int ACTION_SCROLL = 8; public static final int ACTION_HOVER_ENTER = 9; public static final int ACTION_HOVER_EXIT = 10;
pointerIndex:
public static final int ACTION_POINTER_INDEX_MASK = 0xff00; //用于获取低2字节中的高8位. public static final int ACTION_POINTER_INDEX_SHIFT = 8; //因为要从高8位移到低8位. 以下这些都过时了----而且是错的, 不要按这个来了. public static final int ACTION_POINTER_1_DOWN = ACTION_POINTER_DOWN | 0x0000; = 0x0005; public static final int ACTION_POINTER_2_DOWN = ACTION_POINTER_DOWN | 0x0100; = 0x0105; public static final int ACTION_POINTER_3_DOWN = ACTION_POINTER_DOWN | 0x0200; = 0x0205; public static final int ACTION_POINTER_1_UP = ACTION_POINTER_UP | 0x0000; = 0x0006; public static final int ACTION_POINTER_2_UP = ACTION_POINTER_UP | 0x0100; = 0x0106; public static final int ACTION_POINTER_3_UP = ACTION_POINTER_UP | 0x0200; = 0x0206; public static final int ACTION_POINTER_ID_MASK = 0xff00; public static final int ACTION_POINTER_ID_SHIFT = 8;
注意一点:
ACTION_DOWN 的点 离开时 可能是以 ACTION_POINTER_UP 离开
—-因为可能并不是最后一个点离开的.
而 ACTION_POINTER_DOWN 的点, 可能以 ACTION_UP 离开的
—-因为虽然并不是第0个点按下去, 但可能是最后一个点离开的.
所以, * getAction 拿到的 ACTION_UP 并不总是 第0个按下去点的 离开事件.*
关于 Batch
概述:由于, 我们每次通过 MotionEvent 的去处理 多点触摸事件, 很麻烦:
int getPointerCount() int getPointerId(int pointerIndex) int findPointerIndex(int pointerId) int getPointerId(int pointerIndex)
所以, 思路上: 将 多个 motion event 放到一个 MotionEvent中.
—-即 批处理 的思想.
—-注意:
这个 批处理 只在 事件类型为 ACTION_MOVE 时 才有的,
而 ACT
990f
ION_DOWN/ACTION_UP/ACTION_CANCEL/ACTION_POINTER_DOWN/ACTION_POINTER_UP 都是没有的.
详述:
一个 MotionEvent 中包含的事件有:
最后一个motion event事件 + getHistorySize个历史 motion event事件.
这个方法, 注意一下:
float nativeGetAxisValue(long nativePtr, int axis, int pointerIndex, int historyPos)
涉及的方法有:
float getX() 本质是: nativeGetAxisValue(mNativePtr, AXIS_X, 0, HISTORY_CURRENT); 即, 返回的是 **第0个手指** **最后一个**motion event 的x轴位置, float getX(int pointerIndex) 本质是: nativeGetAxisValue(mNativePtr, AXIS_X, pointerIndex, HISTORY_CURRENT); 即, 返回的是 **第pointerIndex个** 手指 **最后一个**motion event 的x轴位置. float getHistoricalX(int pointerIndex, int pos) 本质是: nativeGetAxisValue(mNativePtr, AXIS_X, pointerIndex, pos); 即, 返回的是 第pointerIndex个 手指 第pos个 motion event 的x轴位置. final long getHistoricalEventTime(int pos) ----这里我就不多贴出来了, 实际上, 不仅仅可以 获得历史 motion event 的 坐标/时, 还可以 获得 压力 等等信息. 这里就不多说了. int getHistorySize() 获得 这个 MotionEvent 中 包含了多少个 历史motion event事件. 只有当 事件类型为 ACTION_MOVE 时, 其返回才不为0; 否则返回0.
处理示例:
void printSamples(MotionEvent ev) { final int historySize = ev.getHistorySize(); final int pointerCount = ev.getPointerCount(); for (int h = 0; h < historySize; h++) { System.out.printf("At time %d:", ev.getHistoricalEventTime(h)); for (int p = 0; p < pointerCount; p++) { System.out.printf(" pointer %d: (%f,%f)", ev.getPointerId(p), ev.getHistoricalX(p, h), ev.getHistoricalY(p, h)); } } System.out.printf("At time %d:", ev.getEventTime()); for (int p = 0; p < pointerCount; p++) { System.out.printf(" pointer %d: (%f,%f)", ev.getPointerId(p), ev.getX(p), ev.getY(p)); } } 注意: 先处理 历史motion event事件(序号越为0, 时间就越早), 最后 再来处理 最近的 motion event事件.
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories