网络测速全解析之一:自定义View基础知识(九)
一、MotionEvent讲解:
单点触控:
事件 | 简介 |
ACTION_DOWN | 手指 初次接触到屏幕 时触发。 |
ACTION_MOVE | 手指 在屏幕上滑动 时触发,会多次触发。 |
ACTION_UP | 手指 离开屏幕 时触发。 |
ACTION_CANCEL | 事件 被上层拦截 时触发。 |
ACTION_OUTSIDE | 手指 不在控件区域 时触发。 |
方法:
方法 | 简介 |
getAction() | 获取事件类型。 |
getX() | 获得触摸点在当前 View 的 X 轴坐标。 |
getY() | 获得触摸点在当前 View 的 Y 轴坐标。 |
getRawX() | 获得触摸点在整个屏幕的 X 轴坐标。 |
getRawY() | 获得触摸点在整个屏幕的 Y 轴坐标。 |
一次简单的交互流程:
手指落下(ACTION_DOWN) -> 多次移动(ACTION_MOVE) -> 离开(ACTION_UP)
两个特殊的事件:ACTION_CANCEL和ACTION_OUTSIDE
多点触控
解决多个手指同时按住屏幕的事件区分方式:编号
事件 | 简介 |
ACTION_DOWN | 第一个 手指 初次接触到屏幕 时触发。 |
ACTION_MOVE | 手指 在屏幕上滑动 时触发,会多次触发。 |
ACTION_UP | 最后一个 手指 离开屏幕 时触发。 |
ACTION_POINTER_DOWN | 有非主要的手指按下(即按下之前已经有手指在屏幕上)。 |
ACTION_POINTER_UP | 有非主要的手指抬起(即抬起之后仍然有手指在屏幕上)。 |
以下事件类型不推荐使用 | ------------------ |
ACTION_POINTER_1_DOWN | 第 2 个手指按下,已废弃,不推荐使用。 |
ACTION_POINTER_2_DOWN | 第 3 个手指按下,已废弃,不推荐使用。 |
ACTION_POINTER_3_DOWN | 第 4 个手指按下,已废弃,不推荐使用。 |
ACTION_POINTER_1_UP | 第 2 个手指抬起,已废弃,不推荐使用。 |
ACTION_POINTER_2_UP | 第 3 个手指抬起,已废弃,不推荐使用。 |
ACTION_POINTER_3_UP | 第 4 个手指抬起,已废弃,不推荐使用。 |
方法:
方法 | 简介 |
getActionMasked() | 与 getAction() 类似,多点触控必须使用这个方法获取事件类型。 |
getActionIndex() | 获取该事件是哪个指针(手指)产生的。 |
getPointerCount() | 获取在屏幕上手指的个数。 |
getPointerId(int pointerIndex) | 获取一个指针(手指)的唯一标识符ID,在手指按下和抬起之间ID始终不变。 |
findPointerIndex(int pointerId) | 通过PointerId获取到当前状态下PointIndex,之后通过PointIndex获取其他内容。 |
getX(int pointerIndex) | 获取某一个指针(手指)的X坐标 |
getY(int pointerIndex) | 获取某一个指针(手指)的Y坐标 |
PointId
追踪事件流,请认准 PointId,这是唯一官方指定标准,不要相信 ActionIndex 那个小婊砸。
getPointerId(int pointerIndex)
历史数据(批处理)
由于我们的设备非常灵敏,手指稍微移动一下就会产生一个移动事件,所以移动事件会产生的特别频繁,为了提高效率,系统会将近期的多个移动事件(move)按照事件发生的顺序进行排序打包放在同一个 MotionEvent 中,与之对应的产生了以下方法:
事件 | 简介 |
getHistorySize() | 获取历史事件集合大小 |
getHistoricalX(int pos) |
获取第pos个历史事件x坐标 (pos < getHistorySize()) |
getHistoricalY(int pos) |
获取第pos个历史事件y坐标 (pos < getHistorySize()) |
getHistoricalX (int pin, int pos) |
获取第pin个手指的第pos个历史事件x坐标 (pin < getPointerCount(), pos < getHistorySize() ) |
getHistoricalY (int pin, int pos) |
获取第pin个手指的第pos个历史事件y坐标 (pin < getPointerCount(), pos < getHistorySize() ) |
注意:
-
pin 全称是 pointerIndex,表示第几个手指,此处为了节省空间使用了缩写。
-
历史数据只有 ACTION_MOVE 事件。
-
历史数据单点触控和多点触控均可以用。
获取事件发生的时间
方法 | 简介 |
getDownTime() | 获取手指按下时的时间。 |
getEventTime() | 获取当前事件发生的时间。 |
getHistoricalEventTime(int pos) | 获取历史事件发生的时间。 |
-
pos 表示历史数据中的第几个数据。( pos < getHistorySize() )
-
返回值类型为 long,单位是毫秒。
获取压力(接触面积大小)
MotionEvent支持获取某些输入设备(手指或触控笔)的与屏幕的接触面积和压力大小,主要有以下方法:
描述中使用了手指,触控笔也是一样的。
方法 | 简介 |
getSize () | 获取第1个手指与屏幕接触面积的大小 |
getSize (int pin) | 获取第pin个手指与屏幕接触面积的大小 |
getHistoricalSize (int pos) | 获取历史数据中第1个手指在第pos次事件中的接触面积 |
getHistoricalSize (int pin, int pos) | 获取历史数据中第pin个手指在第pos次事件中的接触面积 |
getPressure () | 获取第一个手指的压力大小 |
getPressure (int pin) | 获取第pin个手指的压力大小 |
getHistoricalPressure (int pos) | 获取历史数据中第1个手指在第pos次事件中的压力大小 |
getHistoricalPressure (int pin, int pos) | 获取历史数据中第pin个手指在第pos次事件中的压力大小 |
pin 全称是 pointerIndex,表示第几个手指。(pin < getPointerCount() )
pos 表示历史数据中的第几个数据。( pos < getHistorySize() )
注意:
1、获取接触面积大小和获取压力大小是需要硬件支持的。
2、非常不幸的是大部分设备所使用的电容屏不支持压力检测,但能够大致检测出接触面积。
3、大部分设备的 getPressure() 是使用接触面积来模拟的。
4、由于某些未知的原因(可能系统版本和硬件问题),某些设备不支持该方法。
我用不同的设备对这两个方法进行了测试,然而不同设备测试出来的结果不相同,之后经过我多方查证,发现是系统问题,有的设备上只有 getSize() 能用,有的设备上只有 getPressure() 能用,而有的则两个都不能用。
由于获取接触面积和获取压力大小受系统和硬件影响,使用的时候一定要进行数据检测,以防因为设备问题而导致程序出错。
鼠标事件
由于触控笔事件和手指事件处理流程大致相同,所以就不讲解了,这里讲解一下与鼠标相关的几个事件:
事件 | 简介 |
ACTION_HOVER_ENTER | 指针移入到窗口或者View区域,但没有按下。 |
ACTION_HOVER_MOVE | 指针在窗口或者View区域移动,但没有按下。 |
ACTION_HOVER_EXIT | 指针移出到窗口或者View区域,但没有按下。 |
ACTION_SCROLL | 滚轮滚动,可以触发水平滚动(AXIS_HSCROLL)或者垂直滚动(AXIS_VSCROLL) |
注意:
1、这些事件类型是 安卓4.0 (API 14) 才添加的。
2、使用 ` getActionMasked()` 获得这些事件类型。
3、这些事件不会传递到 onTouchEvent(MotionEvent) 而是传递到 onGenericMotionEvent(MotionEvent) 。
输入设备类型判断
输入设备类型判断也是安卓4.0 (API 14) 才添加的,主要包括以下几种设备:
设备类型 | 简介 |
TOOL_TYPE_ERASER | 橡皮擦 |
TOOL_TYPE_FINGER | 手指 |
TOOL_TYPE_MOUSE | 鼠标 |
TOOL_TYPE_STYLUS | 手写笔 |
TOOL_TYPE_UNKNOWN | 未知类型 |
使用 getToolType(int pointerIndex) 来获取对应的输入设备类型,pointIndex可以为0,但必须小于 getPointerCount()。