Search code examples
androidmulti-touch

How does multi-touch really work on Android?


In my use-case there are 2 icons (on GL scene), I'd like to handle their pressed, held, and released state parallel and independently (with 2 fingers).

I have tried many code variations for doing this. Currently this is the best performing but still bad code:

@Override
public boolean onTouch(View v, MotionEvent e) {
    if (v != this) return false;
    boolean down = false;
    switch (e.getActionMasked()) {
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_MOVE:
        case MotionEvent.ACTION_POINTER_DOWN:
            down = true;
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_POINTER_UP:
        case MotionEvent.ACTION_OUTSIDE:
        case MotionEvent.ACTION_CANCEL:
            down = false;
            break;
    }

    boolean handled = e.getPointerCount() > 0;
    for(int i = 0; i < e.getPointerCount(); i++) {
        e.getPointerCoords(i, coords);
        int pointer = e.getPointerId(i);
        if (down) {
            scene.sizes.pixelToCm(vec, coords.x, coords.y);
            touchMap.set(pointer, vec.getX(), vec.getY());
        } else {
            touchMap.clear(pointer);
        }
    }
    return true;
}

In this case, when I press and hold icon A, it is Okay. Than I still hold icon A and press icon B, it is also Okay, both icons are pressed. But when I release icon B, icon A also gets released for a moment.

I guess the onTouch() event handler gets an UP event, but its pointer list (e.getPointerCount(), e.getPointerCoords()) also includes pointers which are DOWN.

Anyone please could help me to resolve this situation?


Solution

  • This code seems to do what I expect:

    @Override
    public boolean onTouch(View v, MotionEvent e) {
        if (v != this) return false;
        for(int i = 0; i < 8; i++)
            touchMap.clear(i);
        if (e.getActionMasked() ==  MotionEvent.ACTION_UP) {
            return true;
        }
        for(int i = 0; i < e.getPointerCount(); i++) {
            e.getPointerCoords(i, coords);
            int pointer = e.getPointerId(i);
            scene.sizes.pixelToCm(vec, coords.x, coords.y);
            touchMap.set(pointer, vec.getX(), vec.getY());
    
        }
        return true;
    }