Реализация перетаскивания с мультитач в Android

Я ищу способ реализовать перетаскивание с помощью мультитач в моем приложении. У меня много представлений, и я хочу, чтобы первый пользователь перетаскивал представление одновременно с тем, как второй пользователь перетаскивал другое представление.

Мое перетаскивание одним касанием работает хорошо, вот часть моего кода (мои представления реализуют этот слушатель. OnDragStart записывает затронутую точку, onDragContinuing изменяет положение представления, а onDrop проверяет, действительна ли позиция):

public boolean onTouch(View v, MotionEvent event) {

    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        return onDragStart(event.getX(), event.getY());
    }

    else if (event.getAction() == MotionEvent.ACTION_MOVE){
        return onDragContinuing(event.getRawX(), event.getRawY());                      
    }

    else if (event.getAction() == MotionEvent.ACTION_UP){
        return onDrop(event.getRawX(), event.getRawY());
    }

    else{
        return false;
    }

}

Я пробовал реализовать такой мультитач, но он не работает:

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

public boolean onTouch(View v, MotionEvent event) {

    int action = event.getAction();
    int actionCode = action & MotionEvent.ACTION_MASK;

    switch(actionCode){

        case MotionEvent.ACTION_DOWN :{
            Toast.makeText(getContext(), "down", Toast.LENGTH_SHORT).show();
            // Save the ID of this pointer
            mActivePointerId = event.getPointerId(0);
            return onDragStart(event.getX(), event.getY());
        }

        case MotionEvent.ACTION_POINTER_DOWN :{
            Toast.makeText(getContext(), "pointer down", Toast.LENGTH_SHORT).show();
            // Save the ID of this pointer
            // Extract the index of the pointer that left the touch sensor
            final int pointerIndex = (action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
            mActivePointerId = event.getPointerId(pointerIndex);
            return onDragStart(event.getX(mActivePointerId), event.getY(mActivePointerId));
        }

        case MotionEvent.ACTION_MOVE :{
            Toast.makeText(getContext(), "move", Toast.LENGTH_SHORT).show();
            final int pointerIndex = (action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
            final int mCurrentPointerId = event.getPointerId(pointerIndex);
            if (mActivePointerId == mCurrentPointerId){
                return onDragContinuing(getRawX(event, mActivePointerId), getRawY(event, mActivePointerId));
            }
            else return false;
        }

        case MotionEvent.ACTION_UP :{
            Toast.makeText(getContext(), "up", Toast.LENGTH_SHORT).show();
            final int pointerIndex = (action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
            final int mCurrentPointerId = event.getPointerId(pointerIndex);

            if (mActivePointerId == mCurrentPointerId){
                return onDrop(event.getRawX(), event.getRawY());
            }
            else return false;

        }

        case MotionEvent.ACTION_POINTER_UP :{
            Toast.makeText(getContext(), "pointer up", Toast.LENGTH_SHORT).show();
            final int pointerIndex = (action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
            final int mCurrentPointerId = event.getPointerId(pointerIndex);

            if (mActivePointerId == mCurrentPointerId){
                return onDrop(getRawX(event, pointerIndex), getRawY(event, pointerIndex));
            }
            else return false;

        }

        default :{
            return false;
        }

    }

}

/**
 * MotionEvent has no getRawX(int) method; simulate it pending future API approval. 
 */
private static float getRawX(MotionEvent event, int pointerIndex) {
    float offset = event.getX() - event.getRawX();
    return event.getX(pointerIndex) + offset;
}

/**
 * MotionEvent has no getRawY(int) method; simulate it pending future API approval. 
 */
private static float getRawY(MotionEvent event, int pointerIndex) {
    float offset = event.getY() - event.getRawY();
    return event.getY(pointerIndex) + offset;
}

Что случилось ? Вы можете мне помочь ? Спасибо вам !


person Sébastien BATEZAT    schedule 12.03.2012    source источник
comment
прошло около десяти лет, этот вопрос все еще не решен   -  person Long    schedule 12.06.2021


Ответы (1)


Я нашел решение и объяснение.

Android не поддерживает мультитач в нескольких представлениях, мультитач только для одного просмотра. Итак, чтобы иметь мультитач для нескольких представлений, нам нужно было поймать событие касания в основном действии и сгенерировать новое событие для дочерних представлений.

Спасибо Паскалю Велшу и его блогу (http://www.passsy.de/multitouch-for-all-views/) и исправление ошибки в его коде, которую я обнаружил (http://code.google.com/p/friendbattle/issues/detail?id=19), я решил свою проблему.

Надеюсь, это поможет другим :-)

person Sébastien BATEZAT    schedule 28.03.2012