MotionEvent 补遗:TouchSlop 和 Pointer

TouchSlop

我们知道,Android 将我们的操作大致分为 DOWN - MOVE - UP 等几个事件,然而我们在实际中会发现,只要手机接触到屏幕,就会触发 MOVE 事件(因为我们的手指总是不自主的会抖动,而这种细小的抖动,也会被系统检测到),那么问题来了:究竟多长距离的 MOVE 才算是“手指滑动”,而不是“手指抖动”呢?

Android 提供了一个常量:TouchSlop,这常量被认为是滑动事件的“临界点”。当然,各个手机厂家修改后的系统,该“临界点”也会有不同。

我们可以通过如下方法获取到该常量:

int touchSlop = ViewConfiguration.get(this).getScaledTouchSlop();

关于 ViewConfiguration 的其他使用请看这里:Android ViewConfiguration配置说明

有了参照值,我们需要的就是获取我们手指的移动距离了。

MotionEvent 提供了 getX、getY、getRawX 和 getRawY 四个方法来获取我们手指的位置:

  • 相对于 View:

    • getX:触摸点相对于组件左边界的距离
    • getY:触摸点相对于组件上边界的距离
  • 相对于屏幕

    • getRawX:触摸点对于屏幕左边界的距离
    • getRawY:触摸点对于屏幕上边界的距离

他们获取的值的单位都是像素。

View 也提供了一些关于位置的方法:

  • getTop():View 自身的顶边到其父布局顶边的距离
  • getLeft():View 自身的左边到其父布局左边的距离
  • getRight():View 自身的右边到其父布局左边的距离
  • getBottom():View 自身底边到其父布局顶边的距离

看图:

这样一来,我们就可以判断我们的触摸是否可以触发“滑动”常量了。

Pointer

有时候我们需要多个手指操作屏幕,例如缩放。

为了表示多点触摸,MotionEvent 引入了一个 Pointer 的概念,每个触摸点都是一个 Pointer,每个 Pointer 都有自己的坐标、事件类型。

一个 MotionEvent 对象可以包含多个 Pointer,每个 Pointer 都有自己的 id 和 index。我们通过 event.getActionIndex() 方法来获取 Pointer 的 index,通过 event.findPointerIndex(actionIndex) 来获取 Pointer 的 id。需要注意的是,Pointer 的不同的 MotionEvent 当中的 index 不同的,但 id 却是不会变化的。

那么问题又随之而来,我们如何判断我们的事件是哪个 Pointer 呢?

除了 Pointer 的概念,MotionEvent 还引入了两个事件类型:

  • ACTION_POINTER_DOWN:表示用户又有一根手指触摸到了屏幕

    • ACTION_POINTER_UP:表示用户的一根手指离开屏幕,但还有其他手指触摸屏幕