Android触控基础:MotionEvent

  • Post author:
  • Post category:其他





之前的文章层从Framework层介绍了Android Touch事件即(MotionEvent)的传递机制。本文将详细介绍MotionEvent的一些成员和方法。了解了MotionEvent对开发一些特效如拖动控件或多点缩放控件有很大的作用。同时,掌握MotionEvent类也是学好android触控技术的基础。



一、一些常量


常见的动作常量:


public static final int ACTION_DOWN             = 0;


单点触摸动作



public static final int ACTION_UP               = 1;

单点触摸离开动作


public static final int ACTION_MOVE             = 2;

触摸点移动动作


public static final int ACTION_CANCEL           = 3;触摸动作取消

public static final int ACTION_OUTSIDE          = 4;触摸动作超出边界

public static final int ACTION_POINTER_DOWN     = 5;多点触摸动作

public static final int ACTION_POINTER_UP       = 6;多点离开动作

以下是一些非touch事件

public static final int ACTION_HOVER_MOVE       = 7;

public static final int ACTION_SCROLL           = 8;

public static final int ACTION_HOVER_ENTER      = 9;

public static final int ACTION_HOVER_EXIT       = 10;



掩码常量




ACTION_MASK = 0X000000ff




动作掩码




ACTION_POINTER_INDEX_MASK = 0X0000ff00




触摸点索引掩码



ACTION_POINTER_INDEX_SHIF

T = 8 获取触摸点索引需要移动的位数



二、相关方法




getAction()方法返回的是int类型,用到的只有低16位,


其中:低八位是动作的类型,高8位是触摸点索引值的表示(单点为0,双点为1)



获得动作类型: int action = event.getAction() &

ACTION_MASK 或者使用 getActionMasked()



获得触摸点索引类型: int pointerIndex = (event.getAction() &


ACTION_POINTER_INDEX_MASK ) >> ACTION_POINTER_INDEX_SHIFT








或者使用 getActionIndex()



为什么要有索引信息?



有了索引信息,我们可以在onTOuchEvent事件中判断传进来的MotionEvent对象对应的是单点信息还是多点信息。


下面的代码段能使用户在屏幕上拖动一个对象。它记录了初始点的位置,计算点移动的距离,并将对象移动到新的位置。它正确的处理了这种情况:当第一个手指把控件拖到一个位置,然后按下第二个手指,且第二个手指与同一个控件上。当用户抬起第一个手指时,控件不会跑到第二个手指的位置同时第二个手指可以继续拖动控件。


// The ‘active pointer’ is the one currently moving our object.
private int mActivePointerId = INVALID_POINTER_ID;

@Override
public boolean onTouchEvent(MotionEvent ev) {
    // Let the ScaleGestureDetector inspect all events.
    mScaleDetector.onTouchEvent(ev);
             
    final int action = MotionEventCompat.getActionMasked(ev); 
        
    switch (action) { 
    case MotionEvent.ACTION_DOWN: {
        final int pointerIndex = MotionEventCompat.getActionIndex(ev); 
        final float x = MotionEventCompat.getX(ev, pointerIndex); 
        final float y = MotionEventCompat.getY(ev, pointerIndex); 
            
        // Remember where we started (for dragging)
        mLastTouchX = x;
        mLastTouchY = y;
        // Save the ID of this pointer (for dragging)
        mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
        break;
    }
            
    case MotionEvent.ACTION_MOVE: {
        // Find the index of the active pointer and fetch its position
        final int pointerIndex = 
                MotionEventCompat.findPointerIndex(ev, mActivePointerId);  
            
        final float x = MotionEventCompat.getX(ev, pointerIndex);
        final float y = MotionEventCompat.getY(ev, pointerIndex);
            
        // Only move if the ScaleGestureDetector isn't processing a gesture.
        if (!mScaleDetector.isInProgress()) {
            // Calculate the distance moved
            final float dx = x - mLastTouchX;
            final float dy = y - mLastTouchY;

            mPosX += dx;
            mPosY += dy;

            invalidate();
        }
        // Remember this touch position for the next move event
        mLastTouchX = x;
        mLastTouchY = y;

        break;
    }
            
    case MotionEvent.ACTION_UP: {
        mActivePointerId = INVALID_POINTER_ID;
        break;
    }
            
    case MotionEvent.ACTION_CANCEL: {
        mActivePointerId = INVALID_POINTER_ID;
        break;
    }
        
    case MotionEvent.ACTION_POINTER_UP: {
            
        final int pointerIndex = MotionEventCompat.getActionIndex(ev); 
        final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); 

        if (pointerId == mActivePointerId) {
            // This was our active pointer going up. Choose a new
            // active pointer and adjust accordingly.
            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
            mLastTouchX = MotionEventCompat.getX(ev, newPointerIndex); 
            mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex); 
            mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
        }
        break;
    }
    }       
    return true;
}


MotionEvent还包含了移动操作中其它历史移动数据以


方便处理触控的移动操作.


android sdk对于这个类的描述中就有这么一句:

For efficiency, motion events with ACTION_MOVE may batch together multiple movement samples within a single object.





版权声明:本文为bigconvience原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。