正常开发中,单点触控场景遇到的比较多,比如识别 ACTION_DOWN、ACTION_UP、ACTION_MOVE 事件等。接下来我要介绍的是如何识别多点触控,即多个手指触摸屏幕。
一、MotionEvent事件的分类
官方文档:https://developer.android.com/training/gestures/multi?hl=zh_cn
属性说明:
- ACTION_DOWN:轻触屏幕的第一个手指,也是最先触发的事件。
- ACTION_POINTER_DOWN:除了第一个手指之外,其他手指点击屏幕将触发该事件。
- ACTION_POINTER_UP:除了最后一个手指,其他手指离开屏幕时会调用该事件。
- ACTION_UP:最后一个手指离开屏幕时调用该事件。
- ACTION_MOVE:手指移动时触发该事件。
获取具体手指id:
如果有两根手指在屏幕上,一根手指移动,另外一根手指保持禁止,ACTION_MOVE 中如何才能识别具体是哪根手指进行了移动?
虽然Android没有直接提供api进行调用,但是可以使用其他方法进行获取。
// 获取当前事件的手指id
motionEvent.getPointerId(motionEvent.getActionIndex()));
// 可以监控到多指事件但是回调的id不是ACTION_POINTER_DOWN和ACTION_POINTER_UP,下面会具体说明
event.getAction();
// 必须使用这个方法获取ACTION_POINTER_DOWN和ACTION_POINTER_UP的id
event.getActionMasked();
二、代码示例
主要代码如下:
@Override
public boolean onTouchEvent(MotionEvent event) {
// 获取当前手指的id
int pointerId = event.getPointerId(event.getActionIndex());
// 识别多指必须使用getActionMasked()方法
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
// 第一根手指点击屏幕
Log.d(TAG, "ACTION_DOWN pointerId: " + pointerId);
break;
case MotionEvent.ACTION_POINTER_DOWN:
// 屏幕上已存在手指,再点击会触发这个回调
Log.d(TAG, "ACTION_POINTER_DOWN pointerId: " + pointerId);
break;
case MotionEvent.ACTION_POINTER_UP:
//当屏幕上一根手指被抬起,此时屏幕上仍有别的手指
Log.d(TAG, "ACTION_POINTER_UP pointerId: " + pointerId);
break;
case MotionEvent.ACTION_UP:
//最后一根手指离开屏幕
Log.d(TAG, "ACTION_UP pointerId: " + pointerId);
break;
default:
break;
}
return super.onTouchEvent(event);
}
将食指、中指触摸屏幕,然后再放开中指和食指,运行结果如下:
D/MainActivity: ACTION_DOWN pointerId: 0
D/MainActivity: ACTION_POINTER_DOWN pointerId: 1
D/MainActivity: ACTION_POINTER_UP pointerId: 1
D/MainActivity: ACTION_UP pointerId: 0
三、getAction、getActionMask、getActionIndex区别
可以先看下三个方法的源码:
public static final int ACTION_MASK = 0xff;
public static final int ACTION_POINTER_INDEX_MASK = 0xff00;
public static final int ACTION_POINTER_INDEX_SHIFT = 8;
// 返回触控的所有信息
public final int getAction() {
return nativeGetAction(mNativePtr);
}
// 返回当前触控的动作信息,即低8位的信息
public final int getActionMasked() {
return nativeGetAction(mNativePtr) & ACTION_MASK;
}
// 获取当前触控的索引(比如:当你要监听是哪一个手指在屏幕上移动)
public final int getActionIndex() {
return (nativeGetAction(mNativePtr) & ACTION_POINTER_INDEX_MASK)
>> ACTION_POINTER_INDEX_SHIFT;
}
安卓中使用32位(int)来存储触控事件的动作信息和触控索引。高16位暂时不用,后16位中高8位存储触控信息,低8位存储动作信息。
- ACTION_MASK:动作信息掩码,用于截取目标动作信息;
- ACTION_POINTER_INDEX_MASK:高8位的位置信息掩码,用于截取索引信息;
- ACTION_POINTER_INDEX_SHIFT:截取触控索引时所需的移位个数;
- getAction():返回触控的所有信息
- getActionMasked():返回当前触控的动作信息,即低8位的信息
- getActionIndex():获取当前触控的索引(比如:当你要监听是哪一个手指在屏幕上移动)
单词mask的意思是掩藏掩饰,在这里所表达的含义就是要把一部分信息掩饰掉,只保留要想的信息,无论是使用getAction还是getActionMasked,触屏事件都会回调到onTouchEvent,在多点操控时,以双指按下屏幕为例,系统会多回调一个值表示双指按下,如果使用getAction的话,这个值是261,如果使用getActionMasked这个值是5,所以对于多点操控,android只是多回调了一次,由于android使用低8位表示touch的具体动作,所以如果想在多点触控时做一些事情就需要使用getActionMasked,当然如果你不嫌麻烦,你可以可以使用硬编码的方式使用261(这个值目前已经不推荐使用了)。
参考:
https://blog.csdn.net/victory08/article/details/49101367
https://blog.csdn.net/woshimalingyi/article/details/50383578
网友评论