Code example for MotionEvent

Methods: getActiongetEventTimegetPointerIdgetXgetY

0
    private int getPointersDown() { 
        return mPointerInfo.size();
    } 
 
    private int getActionIndex(MotionEvent event) {
        return (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
            >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
    } 
 
    private void onTouchStart(MotionEvent event) {
        mLastEventTime = event.getEventTime();
        mPointerInfo.addFirst(PointerInfo.create(event, getActionIndex(event)));
        if (getPointersDown() == 2) { 
            sendScaleGesture(EventType.BEGIN);
        } 
    } 
 
    private void onTouchMove(MotionEvent event) {
        mLastEventTime = event.getEventTime();
        for (int i = 0; i < event.getPointerCount(); i++) {
            PointerInfo pointerInfo = pointerInfoForEventIndex(event, i);
            if (pointerInfo != null) {
                pointerInfo.populate(event, i);
            } 
        } 
 
        if (getPointersDown() == 2) { 
            sendScaleGesture(EventType.CONTINUE);
        } 
    } 
 
    private void onTouchEnd(MotionEvent event) {
        mLastEventTime = event.getEventTime();
 
        int id = event.getPointerId(getActionIndex(event));
        ListIterator<PointerInfo> iterator = mPointerInfo.listIterator();
        while (iterator.hasNext()) {
            PointerInfo pointerInfo = iterator.next();
            if (pointerInfo.getId() != id) {
                continue; 
            } 
 
            // One of the pointers we were tracking was lifted. Remove its info object from the 
            // list, recycle it to avoid GC pauses, and send an onScaleEnd() notification if this 
            // ended the gesture. 
            iterator.remove();
            pointerInfo.recycle();
            if (getPointersDown() == 1) { 
                sendScaleGesture(EventType.END);
            } 
        } 
    } 
 
    /** 
     * Returns the X coordinate of the focus location (the midpoint of the two fingers). If only 
     * one finger is down, returns the location of that finger. 
     */ 
    public float getFocusX() { 
        switch (getPointersDown()) { 
        case 1: 
            return mPointerInfo.getFirst().getCurrent().x;
        case 2: 
            PointerInfo pointerA = mPointerInfo.getFirst(), pointerB = mPointerInfo.getLast();
            return (pointerA.getCurrent().x + pointerB.getCurrent().x) / 2.0f;
        } 
 
        Log.e(LOGTAG, "No gesture taking place in getFocusX()!");
        return 0.0f; 
    } 
 
    /** 
     * Returns the Y coordinate of the focus location (the midpoint of the two fingers). If only 
     * one finger is down, returns the location of that finger. 
     */ 
    public float getFocusY() { 
        switch (getPointersDown()) { 
        case 1: 
            return mPointerInfo.getFirst().getCurrent().y;
        case 2: 
            PointerInfo pointerA = mPointerInfo.getFirst(), pointerB = mPointerInfo.getLast();
            return (pointerA.getCurrent().y + pointerB.getCurrent().y) / 2.0f;
        } 
 
        Log.e(LOGTAG, "No gesture taking place in getFocusY()!");
        return 0.0f; 
    } 
 
    /** Returns the most recent distance between the two pointers. */ 
    public float getCurrentSpan() { 
        if (getPointersDown() != 2) { 
            Log.e(LOGTAG, "No gesture taking place in getCurrentSpan()!");
            return 0.0f; 
        } 
 
        PointerInfo pointerA = mPointerInfo.getFirst(), pointerB = mPointerInfo.getLast();
        return PointUtils.distance(pointerA.getCurrent(), pointerB.getCurrent());
    } 
 
    /** Returns the second most recent distance between the two pointers. */ 
    public float getPreviousSpan() { 
        if (getPointersDown() != 2) { 
            Log.e(LOGTAG, "No gesture taking place in getPreviousSpan()!");
            return 0.0f; 
        } 
 
        PointerInfo pointerA = mPointerInfo.getFirst(), pointerB = mPointerInfo.getLast();
        PointF a = pointerA.getPrevious(), b = pointerB.getPrevious();
        if (a == null || b == null) {
            a = pointerA.getCurrent();
            b = pointerB.getCurrent();
        } 
 
        return PointUtils.distance(a, b);
    } 
 
    /** Returns the time of the last event related to the gesture. */ 
    public long getEventTime() { 
        return mLastEventTime;
    } 
 
    /** Returns true if the scale gesture is in progress and false otherwise. */ 
    public boolean isInProgress() { 
        return getPointersDown() == 2; 
    } 
 
    /* Sends the requested scale gesture notification to the listener. */ 
    private void sendScaleGesture(EventType eventType) {
        switch (eventType) {
        case BEGIN:     mListener.onScaleBegin(this);   break;
        case CONTINUE:  mListener.onScale(this);        break;
        case END:       mListener.onScaleEnd(this);     break;
        } 
    } 
 
    /* 
     * Returns the pointer info corresponding to the given pointer index, or null if the pointer 
     * isn't one that's being tracked. 
     */ 
    private PointerInfo pointerInfoForEventIndex(MotionEvent event, int index) {
        int id = event.getPointerId(index);
        for (PointerInfo pointerInfo : mPointerInfo) {
            if (pointerInfo.getId() == id) {
                return pointerInfo;
            } 
        } 
        return null; 
    } 
 
    private enum EventType { 
        BEGIN,
        CONTINUE,
        END,
    } 
 
    /* Encapsulates information about one of the two fingers involved in the gesture. */ 
    private static class PointerInfo { 
        /* A free list that recycles pointer info objects, to reduce GC pauses. */ 
        private static Stack<PointerInfo> sPointerInfoFreeList;
 
        private int mId;
        private PointF mCurrent, mPrevious;
 
        private PointerInfo() { 
            // External users should use create() instead. 
        } 
 
        /* Creates or recycles a new PointerInfo instance from an event and a pointer index. */ 
        public static PointerInfo create(MotionEvent event, int index) {
            if (sPointerInfoFreeList == null) {
                sPointerInfoFreeList = new Stack<PointerInfo>();
            } 
 
            PointerInfo pointerInfo;
            if (sPointerInfoFreeList.empty()) {
                pointerInfo = new PointerInfo();
            } else { 
                pointerInfo = sPointerInfoFreeList.pop();
            } 
 
            pointerInfo.populate(event, index);
            return pointerInfo;
        } 
 
        /* 
         * Fills in the fields of this instance from the given motion event and pointer index 
         * within that event. 
         */ 
        public void populate(MotionEvent event, int index) {
            mId = event.getPointerId(index);
            mPrevious = mCurrent;
            mCurrent = new PointF(event.getX(index), event.getY(index));
        } 
 
        public void recycle() { 
            mId = -1;
            mPrevious = mCurrent = null;