Android图片处理总结二:(图片手势控制)MotionEvent解析

Android用一个32位的整型值表示一次TouchEvent事件,那就是MotionEvent,包括坐标信息、点击等事件,下面总结下这个类。

获取事件坐标

  • getX()和getY()
    由这两个函数获得的x,y值是相对的坐标值,相对于消费这个事件的视图的左上点的坐标。

  • getRawX()和getRawY()
    由这两个函数获得的x,y值是绝对坐标,是相对于屏。
    引用两张网上的图来说明:

这里写图片描述

这里写图片描述

获取事件类型

获取事件类型涉及到三个方法:getAction(),getActionMasked(),getActionIndex()
1. getAction:触摸动作的原始32位信息,包括事件的动作,触控点信息
2. getActionMasked:触摸的动作,按下,抬起,滑动,多点按下,多点抬起
3. getActionIndex:触控点信息
以下是SDK中三个方法的定义:

public final int getAction() {
        return nativeGetAction(mNativePtr);
}
public final int getActionMasked() {
       return nativeGetAction(mNativePtr) & ACTION_MASK;
}
public final int getActionIndex() {
        return (nativeGetAction(mNativePtr) & ACTION_POINTER_INDEX_MASK)
                >> ACTION_POINTER_INDEX_SHIFT;
}

从上面方法可以看出getActionMasked()是getAction()的低8位,getActionIndex()是getAction()的高8位。

  • getAction()的高8位,即getActionIndex()是用来记录多点触控时候的触控点信息的
  • 单点触控的时候,getAction()等于getActionMasked(),getActionIndex()等于0

    如果getAction()的值是0x0000,则表示是第一个触控点的ACTION_DOWN操作。
    如果getAction()的值是0x0100呢,则表示是第二个触控点的ACTION_DOWN操作。

    第三个的ACTION_DOWN呢?相信你可以推出来是0x0200。

获取触控时间

  • getDownTime()
    指触摸事件开始的时间,即按下的时间,这时候会收到ACTION_DOWN的事件。
  • getEventTime()
    指触摸事件结束的时间,这时候会收到ACTION_UP或者ACTION_CANCEL事件
    getEventTime()与getDownTime()的差就是本次事件总共花费的时间。

多点触控

 为了可以表示多个触摸点的动作,MotionEvent中引入了Pointer的概念,一个pointer就代表一个触摸点,每个pointer都有自己的事件类型,也有自己的横轴坐标值。一个MotionEvent对象中可能会存储多个pointer的相关信息,每个pointer都会有一个自己的id和index。pointer的id在整个事件流中是不会发生变化的,但是index会发生变化。
 MotionEvent类中的很多方法都是可以传入一个int值作为参数的,其实传入的就是pointer的index值。比如getX(pointerIndex)和getY(pointerIndex),此时,它们返回的就是index所代表的触摸点相关事件坐标值。
 由于pointer的index值在不同的MotionEvent对象中会发生变化,但是id值却不会变化。所以,当我们要记录一个触摸点的事件流时,就只需要保存其id,然后使用findointerIndex(int)来获得其index值,然后再获得其他信息。


 private final static int INVALID_ID = -1;
    private int mActivePointerId = INVALID_ID;
    private int mSecondaryPointerId = INVALID_ID;
    private float mPrimaryLastX = -1;
    private float mPrimaryLastY = -1;
    private float mSecondaryLastX = -1;
    private float mSecondaryLastY = -1;
    public boolean onTouchEvent(MotionEvent event)
    {
        int action = MotionEventCompat.getActionMasked(event);
        switch (action)
        {
            case MotionEvent.ACTION_DOWN:
                int index = event.getActionIndex();
                mActivePointerId = event.getPointerId(index);
                mPrimaryLastX = MotionEventCompat.getX(event,index);
                mPrimaryLastY = MotionEventCompat.getY(event,index);
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                index = event.getActionIndex();
                mSecondaryPointerId = event.getPointerId(index);
                mSecondaryLastX = event.getX(index);
                mSecondaryLastY = event.getY(index);
                break;
            case MotionEvent.ACTION_MOVE:
                index = event.findPointerIndex(mActivePointerId);
                int secondaryIndex = MotionEventCompat.findPointerIndex(event,mSecondaryPointerId);
                final float x = MotionEventCompat.getX(event,index);
                final float y = MotionEventCompat.getY(event,index);
                final float secondX = MotionEventCompat.getX(event,secondaryIndex);
                final float secondY = MotionEventCompat.getY(event,secondaryIndex);
                break;
            case MotionEvent.ACTION_POINTER_UP:                 break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mActivePointerId = INVALID_ID;
                mPrimaryLastX =-1;
                mPrimaryLastY = -1;
                break;
        }
        return true;
    }

除了pointer的概念,MotionEvent还引入了两个事件类型:
• ACTION_POINTER_DOWN:代表用户又使用一个手指触摸到屏幕上,也就是说,在已经有一个触摸点的情况下,有新出现了一个触摸点。
• ACTION_POINTER_UP:代表用户的一个手指离开了触摸屏,但是还有其他手指还在触摸屏上。也就是说,在多个触摸点存在的情况下,其中一个触摸点消失了。它与ACTION_UP的区别就是,它是在多个触摸点中的一个触摸点消失时(此时,还有触摸点存在,也就是说用户还有手指触摸屏幕)产生,而ACTION_UP可以说是最后一个触摸点消失时产生。

 那么,用户先两个手指先后接触屏幕,同时滑动,然后在先后离开这一套动作所产生的事件流是什么样的呢?
 它所产生的事件流如下:
•先产生一个ACTION_DOWN事件,代表用户的第一个手指接触到了屏幕。
•再产生一个ACTION_POINTER_DOWN事件,代表用户的第二个手指接触到了屏幕。
•很多的ACTION_MOVE事件,但是在这些MotionEvent对象中,都保存着两个触摸点滑动的信息,相关的代码我们会在文章的最后进行演示。
•一个ACTION_POINTER理理
UP事件,代表用户的一个手指离开了屏幕。
•如果用户剩下的手指还在滑动时,就会产生很多ACTION_MOVE事件。
•一个ACTION_UP事件,代表用户的最后一个手指离开了屏幕

批处理

为了效率,Android系统在处理ACTION_MOVE事件时会将连续的几个多触点移动事件打包到一个MotionEvent对象中。我们可以通过getX(int)和getY(int)来获得最近发生的一个触摸点事件的坐标,然后使用getHistorical(int,int)和getHistorical(int,int)来获得时间稍早的触事件的坐标,二者是发生时间先后的关系。所以,我们应该先处理通过getHistoricalXX相关函数获得的事件信息,然后在处理当前的事件信息。
 下边就是Android Guide中相关的例子:

    void printSamples(MotionEvent ev) 
    { 
        final int historySize = ev.getHistorySize(); 
        final int pointerCount = ev.getPointerCount();
        for (int h = 0; h < historySize; h++) 
        { 
            System.out.printf("At time %d:", ev.getHistoricalEventTime(h)); 
            for (int p = 0; p < pointerCount; p++) 
            { 
                System.out.printf(" pointer %d: (%f,%f)", ev.getPointerId(p), ev.getHistoricalX(p, h), ev.getHistoricalY(p, h)); 
            } 
        } 
        System.out.printf("At time %d:", ev.getEventTime()); 
        for (int p = 0; p < pointerCount; p++) 
        { 
            System.out.printf(" pointer %d: (%f,%f)", ev.getPointerId(p), ev.getX(p), ev.getY(p)); 
        } 
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值