Android View之MotionEvent

(一)MotionEvent 单点触控

event.getAction():获取事件类型。

事件类型 说明
ACTION_DOWN 手指按下时触发
ACTION_MOVE 手指在屏幕上滑动时(多次)触发
ACTION_UP 手指离开屏幕时触发
ACTION_CANCEL 手指被上层控件拦截时触发

(二)MotionEvent 多点触控

几个名词解释:

Action:具体的事件类型

pointerIndex:指针(手指)的索引,用于获取具体事件(如:手指的坐标位置)。
注意:落下手指时前面有空缺会优先填补空缺; 而手指抬起时后面的也会向前补位。

pointerId:指针(手指)的唯一标识ID,用于识别是哪个手指。--推荐
注意:pointerId在手指按下和抬起之间ID始终不变。

举例说明:0x 00 00 01 05
01 表示pointerIndex,05 表示Action

event.getActionMasked():获取事件类型。

事件类型 说明
ACTION_DOWN 第一根手指首次按下时触发
ACTION_POINTER_DOWN 其他手指按下时触发
ACTION_MOVE 手指在屏幕上滑动时(多次)触发
ACTION_POINTER_UP 其他手指抬起时触发
ACTION_UP 最后一根手指离开屏幕时触发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 多点触控时获取事件类型(单点触控也可用)
event.getActionMasked();

// 获取该事件是哪个指针(手指)产生的(该方法只对DOWN、UP有效)。
event.getActionIndex();
// 获取一个指针(手指)的唯一标识符ID,拿到PointerId用于追踪事件流--推荐。
// 在手指按下和抬起之间ID始终不变
// 参数:这里的pointerIndex就是actionIndex
event.getPointerId(int pointerIndex);
// 通过PointerId获取到当前状态下PointIndex,之后通过PointerIndex获取其他内容。
event.findPointerIndex(int pointerId);
// 获取在屏幕上指针(手指)的个数。
event.getPointerCount();
// 获取某一个指针(手指)的X坐标
event.getX(int pointerIndex);
// 获取某一个指针(手指)的Y坐标
event.getY(int pointerIndex);

// 获取历史事件集合大小(只记录 ACTION_MOVE 事件,所以单点触控也可以用)
event.getHistorySize();
// 获取第index个手指的第pos个历史事件X坐标
event.getHistoricalX(int index, int pos);
// 获取第index个手指的第pos个历史事件Y坐标
event.getHistoricalY(int index, int pos);

// 手指按下时的时间
event.getDownTime();
// 当前事件发生时的时间
event.getEventTime();
// 获取历史事件发生的时间。注意:pos < getHistorySize()
event.getHistoricalEventTime(int pos);

// 获取第index手指与屏幕的接触面积大小
event.getSize(int index);
// 获取历史数据中第index个手指在第pos次事件中的接触面积
event.getHistoricalSize(int index, int pos);
// 获取第index个手指的压力大小(可能无效)
event.getPressure(int index);
// 获取历史数据中第index个手指在第pos次事件中的压力大小(可能无效)
event.getHistoricalPressure(int index, int pos);

(三)MotionEvent 多点触控实例

实例1:追踪手指的轨迹

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/**
* View - MultiTouch 追踪手指的轨迹
* <p>
* 主要通过 event.getPointerId(event.getActionIndex())来识别是哪根手指(注意:从0开始)
* </p>
*
* @author [*昨日重现*] lhy_ycu@163.com
* @since version 1.0
*/
public class TrackFingerView extends View {
private Paint mPaint;

// 记录第二根手指的位置
private PointF pointF;
// 是否存在第二根手指
private boolean isPointer2 = false;

public TrackFingerView(Context context) {
this(context, null);
}

public TrackFingerView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
pointF = new PointF(0, 0);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
final int index = event.getActionIndex();
switch (event.getActionMasked()) {
case MotionEvent.ACTION_POINTER_DOWN:// 第N根手指按下(N>1)
if (event.getPointerId(index) == 1) {// pointerId从0开始
isPointer2 = true;
pointF.set(event.getX(), event.getY());
}
break;
case MotionEvent.ACTION_POINTER_UP:// 第N根手指抬起(N>1)
if (event.getPointerId(index) == 1) {
isPointer2 = false;
pointF.set(0, 0);
}
break;
case MotionEvent.ACTION_MOVE:
if (event.getPointerId(index) == 1) {
// 获取第二根手指的索引
int pointerIndex = event.findPointerIndex(1);
// 通过索引来获取第二根手指的坐标
pointF.set(event.getX(pointerIndex), event.getY(pointerIndex));
}
break;
case MotionEvent.ACTION_UP:// 最后一根手指抬起
isPointer2 = false;
pointF.set(0, 0);
break;
}
postInvalidateDelayed(20L);
return true;
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

if (isPointer2) {
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(pointF.x, pointF.y, 300, mPaint);
}
}

}

实例2:可拖动的图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/**
* View - MultiTouch 可拖动的图片(这里只处理第一根手指)
*
* @author [*昨日重现*] lhy_ycu@163.com
* @since version 1.0
*/
public class DragBitmapView extends View {
private Paint mPaint;

private Bitmap mBitmap;
// 图片所在区域
private RectF mRectF;
// 记录最后一个点
private PointF mLastPoint;
// 用于数值转换
private Matrix mMatrix;
// 是否可以拖动
private boolean enableDrag;

public DragBitmapView(Context context) {
this(context, null);
}

public DragBitmapView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}

private void init(Context context) {
mPaint = new Paint();
mPaint.setAntiAlias(true);

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;// 缩小2倍
mBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_logo, options);

mRectF = new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
mLastPoint = new PointF();
mMatrix = new Matrix();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
final int index = event.getActionIndex();
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
// 第一根手指 在图片区域内 按下
if (event.getPointerId(index) == 0 && mRectF.contains(event.getX(), event.getY())) {
enableDrag = true;
mLastPoint.set(event.getX(), event.getY());
}
break;
case MotionEvent.ACTION_MOVE:
if (enableDrag) {
int pointerIndex = event.findPointerIndex(0);
// 图片平移后第一根手指最后一个点的坐标
mMatrix.postTranslate(event.getX(pointerIndex) - mLastPoint.x, event.getY(pointerIndex) - mLastPoint.y);
mLastPoint.set(event.getX(pointerIndex), event.getY(pointerIndex));
// 更新图片区域
mRectF.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
mMatrix.mapRect(mRectF);
invalidate();
}
break;
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_UP:
// 第一根手指 释放时复位
if (event.getPointerId(index) == 0) {
enableDrag = false;
}
break;
}
return true;
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, mMatrix, mPaint);
}

}

Hawky wechat
欢迎订阅我的微信公众号
坚持原创技术分享,您的支持将鼓励我继续创作!

分享