安卓手势处理(二) MotionEvent

本文是安卓手势处理系列的第二篇,主要讲解MotionEvent类,包括事件类型、手指id、索引和坐标信息。介绍了如何通过MotionEvent的API获取事件信息,并探讨了ACTION_MASK、ACTION_DOWN等事件类型。同时,文章讨论了手指index和id的区别,以及如何监听特定手指的行为,特别是如何在MOVE事件中监听第二根手指的轨迹。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

系列文章:
安卓手势处理(一)view的位置信息
安卓手势处理(二) MotionEvent
安卓手势处理(三)之实现图片的放大和缩小
安卓手势处理(四)之Fling
安卓手势处理(五)案例

上一篇文章确定了view的位置,这一篇就来讲一下view是如何分辨多个手指的点击事件。

MotionEvent

事件的信息就是封装在MotionEvent这个类之中的,包含事件类型(Action),手指id(pointerId),手指索引(index),事件发生的坐标信息(x,y)。
获取事件坐标位置API:

getX()       //获取相对于该view显示区域左上角的位置x
getY()       //获取相对于该view显示区域左上角的位置y
getRawX()   //获取相对于整个屏幕左上角的位置x
getRawY()   //获取相对于整个屏幕左上角的位置y

获取事件类型API:

public final int getAction() {
        return nativeGetAction(mNativePtr);
}
public final int getActionMasked() {
        return nativeGetAction(mNativePtr) & ACTION_MASK;
}

上面两个API的区别就是有没有ACTION_MASK,ACTION_MASK=0xff,说明最低的八位表示事件类型,常用的事件类型有下面几种:

MotionEvent.ACTION_DOWN
MotionEvent.ACTION_POINTER_DOWN
MotionEvent.ACTION_UP
MotionEvent.ACTION_POINTER_UP
MotionEvent.ACTION_MOVE
MotionEvent.ACTION_CANCEL

具体意义就不解释了
MotionEvent还带有index信息,用以记录手指的index,这个参数是会变化的,同一个手指的index也会随着其他手指的抬起发生变化,然而手指的id是不会变化的,只要这个手指一直在屏幕上,那么id永远不会变化,这样就给我们一种方法用以监视某一个手指的行为,获取id的方法要先获取index:

int index = event.getActionIndex();
int id = event.getPointerId(index);

获取id对应的index:

public final int findPointerIndex(int pointerId) {
        return nativeFindPointerIndex(mNativePtr, pointerId);
}

使用下面的例子来观察id和index的变化:

viewGroup.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                int action = event.getActionMasked();
                int index = event.getActionIndex();
                int id = event.getPointerId(index);
                switch (action) {
                    case MotionEvent.ACTION_DOWN:
                        Log.d(TAG, "ACTION_DOWN" + " index:" + index + ";   id:" + id);
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        Log.d(TAG, "ACTION_POINTER_DOWN" + " index:" + index + ";   id:" + id);
                        break;
                    case MotionEvent.ACTION_UP:
                        Log.d(TAG, "ACTION_UP" + " index:" + index + ";   id:" + id);
                        break;
                    case MotionEvent.ACTION_POINTER_UP:
                        Log.d(TAG, "ACTION_POINTER_UP" + " index:" + index + ";   id:" + id);
                        break;
                    case MotionEvent.ACTION_MOVE:
                        Log.d(TAG, "ACTION_MOVE" + " index:" + index + ";   id:" + id);
                        break;

                    default:
                        break;

                }
                return true;
            }
        });

假如A、B手指先后按下,那么此时的状态是这样的:

A   id:0  index:0
B   id:1  index:1

A手指抬起,此时状态:

B   id:1  index:0

A手指再次按下:

A   id:0  index:1
B   id:1  index:0

B抬起:

A   id:0  index:0

从log可以看出,index会动态变化,只要有其他手指抬起,比这个手指的index大的手指的index都会减小1,但是id是不变的。

还有一点要注意的是,MOVE事件的id总是0,因为MOVE事件是没有手指信息的,不知道为什么安卓没有封装,那么如果我只想监听第二根手指的轨迹,那该怎么办呢?

tv.setOnTouchListener(new View.OnTouchListener() {
            int mOldX;
            int mOldY;
            boolean mSecondDown = false;
            //监听第二根手指
            int mObsever = 1;
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int action = event.getActionMasked();
                int index = event.getActionIndex();
                int id = event.getPointerId(index);
                int currX = (int) event.getRawX(index);
                int currY = (int) event.getRawY(index);
                switch (action) {
                    case MotionEvent.ACTION_DOWN:
                    case MotionEvent.ACTION_POINTER_DOWN:
                        Log.d("HAHA", "ACTION_DOWN" + " index:" + index + ";   id:" + id);
                        if (id == mObsever) {
                            mSecondDown = true;
                            mOldX = currX;
                            mOldY = currY;
                        }
                        break;
                    case MotionEvent.ACTION_MOVE:
                        Log.d("HAHA", "ACTION_MOVE" + " index:" + index + ";   id:" + id);
                        if (mSecondDown) {
                            int x = (int) event.getRawX(event.findPointerIndex(mObsever));
                            int y = (int) event.getRawY(event.findPointerIndex(mObsever));
                            int offsetX = x - mOldX;
                            int offsetY = y - mOldY;
                            tv.setTranslationX(tv.getTranslationX() + offsetX);
                            tv.setTranslationY(tv.getTranslationY() + offsetY);
                            mOldX = x;
                            mOldY = y;
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                    case MotionEvent.ACTION_POINTER_UP:
                        if(id == mObsever){
                            mSecondDown = false;
                        }
                        break;
                    case MotionEvent.ACTION_CANCEL:
                        break;
                }
                return true;
            }
        });

直接在MOVE事件中,获取到第id为1对应的index,然后根据index获取坐标,这样就完成了对任意一根手指事件的监听。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值