MotionEvent
MotionEvent对象是与用户触摸相关的时间序列,该序列从用户首次触摸屏幕开始,经历手指在屏幕表面的任何移动,直到手指离开屏幕时结束。手指的初次触摸(ACTION_DOWN操作),滑动(ACTION_MOVE操作)和抬起(ACTION_UP)都会创建MotionEvent对象。移动过程中也会产生大量事件,每个事件都会产生对应的MotionEvent对象记录发生的操作,触摸的位置,使用的多大压力,触摸的面积,何时发生,以及最初的ACTION_DOWN何时发生等相关的信息。
MotionEvent动作常量:
- MotionEvent.ACTION_DOWN:当屏幕检测到第一个触点按下之后就会触发到这个事件。
- MotionEvent.ACTION_MOVE:当触点在屏幕上移动时触发,触点在屏幕上停留也是会触发的,主要是由于它的灵敏度很高,而我们的手指又不可能完全静止(即使我们感觉不到移动,但其实我们的手指也在不停地抖动)。
- MotionEvent.ACTION_POINTER_DOWN:当屏幕上已经有触点处于按下的状态的时候,再有新的触点被按下时触发。
- MotionEvent.ACTION_POINTER_UP:当屏幕上有多个点被按住,松开其中一个点时触发(即非最后一个点被放开时)触发。
- MotionEvent.ACTION_UP:当触点松开时被触发。
- MotionEvent.ACTION_OUTSIDE: 表示用户触碰超出了正常的UI边界.
- MotionEvent.ACTION_SCROLL:android3.1引入,非触摸滚动,主要是由鼠标、滚轮、轨迹球触发。
- MotionEvent.ACTION_CANCEL:不是由用户直接触发,由系统在需要的时候触发,例如当父view通过使函数onInterceptTouchEvent()返回true,从子view拿回处理事件的控制权时,就会给子view发一个ACTION_CANCEL事件,子view就再也不会收到后续事件了。
MotionEvent方法:
- getAction():返回动作类型,没有掩码的,高位一个字节标志触摸手指的id
- getX()/getY():获得事件发生时,触摸的中间区域的X/Y坐标,由这两个函数获得的X/Y值是相对坐标,相对于消费这个事件的视图的左上角的坐标。
- getRawX()/getRawY():由这两个函数获得的X/Y值是绝对坐标,是相对于屏幕的。
- getSize():指压范围
- getPressure(): 压力值,0-1之间,看情况,很可能始终返回1,具体的级别由驱动和物理硬件决定的
- getEdgeFlags():当事件类型是ActionDown时可以通过此方法获得边缘标记(EDGE_LEFT,EDGE_TOP,EDGE_RIGHT,EDGE_BOTTOM),但是看设备情况,很可能始终返回0
- getDownTime() :按下开始时间
- getEventTime() : 事件结束时间
- getActionMasked():多点触控获取经过掩码后的动作类型 ,是getAction() & 0xff 掩码得到的,去除了高位一个字节的手指id
- getActionIndex():多点触控获取经过掩码和平移后的索引 ,根据这个索引,可以获取触控手指的id,即通过getPointerId(int pointerIndex);索引的范围在[0,getPointerCount()-1]内
- getPointerCount():获取触控点的数量,比如2则可能是两个手指同时按压屏幕
- getPointerId(int pointerIndex):根据索引获取一个触控手指的id,对于每个触控的点的细节,我们可以通过一个循环执行getPointerId方法获取id,标志哪个手指触发的事件
- getX(int pointerIndex):根据索引获取触控点的x位置
- getY(int pointerIndex):根据索引获取触控点的y位置
- getPressure(int pointerIndex):根据索引获取触控点的压力
索引pointerIndex 与 pointerId
pointerIndex
每根手指从按下、移动到离开屏幕,每根手指在每一个事件的Index可能是不固定的,因为受到其它手指的影响。比如,A跟B两根手指同时按在屏幕上,此时A的PointerIndex为0,B的则为1。当A先离开屏幕时,B的PointerIndex则变为了0。PointerIndex的值的不是任意的,它必须在[0,PointerCount-1]的范围内。其中PointerCount为参与触控的手指数量。pointerId
每根手指从按下、移动到离开屏幕,每个手指都会拥有一个固定pointerId。根据索引获取一个触控手指的id,getPointerId(int pointerIndex)。
VelocityTracker
VelocityTracker是一个跟踪触摸事件滑动速度的帮助类,用于实现flinging以及其它类似的手势。它的原理是把触摸事件 MotionEvent 对象传递给VelocityTracker的addMovement(MotionEvent)方法,然后分析MotionEvent 对象在单位时间类发生的位移来计算速度。你可以使用getXVelocity() 或getXVelocity()获得横向和竖向的速率到速率时,但是使用它们之前请先调用computeCurrentVelocity(int)来初始化速率的单位 。
- VelocityTracker obtain();获得一个新的速度跟踪器,如果缓存池中又可用的,返回可用的,没有就new一个。当不使用时,请调用recycle(),若设置了策略会清除状态并进入缓存池。
- void clear()清除状态,回到初始状态
- void recycle()若设置了策略会清除状态并进入缓存池
- addMovement(MotionEvent event) 添加一个事件跟踪
- void computeCurrentVelocity(int units, float maxVelocity)计算当前速度,unitis表示速率的基本时间单位。unitis值为1的表示是,一毫秒时间单位内运动了多少个像素, unitis值为1000表示一秒(1000毫秒)时间单位内运动了多少个像素;maxVelocity为最大的速度,若设置为2,则计算的速度不会大于2
- void computeCurrentVelocity(int units) 计算当前速度,最大的速度为Float.MAX_VALUE
- float getXVelocity() 取出上次计算的x轴方向上的速度,之前请先调用computeCurrentVelocity
- float getYVelocity() 取出上次计算的y轴方向上的速度,之前请先调用computeCurrentVelocity
- float getXVelocity(int id) 取出上次计算的指定id(pointerId)的x轴方向上的速度,之前请先调用computeCurrentVelocity
- float getYVelocity(int id) 取出上次计算的指定id(pointerId)的y轴方向上的速度,之前请先调用computeCurrentVelocity