Понимание Android PointerID. Возврат неожиданного значения

Недавно я получил отчет о сбое для своего приложения и, посмотрев на трассировку стека, понял, что у меня проблема с мультитач-элементами управления.

Что происходит, примерно так:

Я пытаюсь записать нажатия пальцами только на 4 пальца. Больше не надо. Я хочу, чтобы все, что больше 4, эффективно игнорировалось.

Поэтому я делаю что-то вроде этого:

@Override
public boolean onTouchEvent(MotionEvent event) {

    pointerCount = event.getPointerCount();

    if (pointerCount <= 4){

    actionMask = event.getActionMasked();
    pointerIndex = event.getActionIndex();      
    pointerID = event.getPointerId(pointerIndex);
    //etc.............

Так что я ничего не запускаю в onTouch, если более 4 пальцев не работают.

Кажется, это работает нормально, обычно это не "действует" на палец 5, 6 и т. Д. Так что все хорошо. (Я говорю "в общем" из-за того, что следует).....

Эта проблема

Однако, если я скажу, скажем, 6 пальцами вниз, а затем подниму их, последний из помещенных вниз имеет указатель ID, равный 5. На самом деле это не проблема, поскольку я ничего не делаю в action_up или action_pointer_up.

Однако в action_pointer_down 90% времени я получаю ожидаемое поведение, когда любой палец, помещенный вниз, имеет идентификатор от 0 до 3.

Однако, если вы поместите 5 или более пальцев на экран и быстро нажмете на экран снова и снова, в конце концов, событию action_pointer_down будет присвоено значение 4 или более (я видел 4, 5, 6 и 7) Поэтому, когда он пытается поместить эти значения в массивы xList и nList, он вылетает с исключением вне границ.

Это проблема, потому что в action_pointer_down я сохраняю x и y пальца в пару созданных мной массивов. (Эта информация понадобится мне для выполнения некоторых действий позже). Эти массивы имеют размер 4 каждый (поэтому индексы от 0 до 3). Как это:

case MotionEvent.ACTION_POINTER_DOWN:{

    try{                        
            if (isJumpPressed(event.getX(pointerIndex),event.getY(pointerIndex))){
                 //Jump here
            }


            else if (isLeftPressed(event.getX(pointerIndex),event.getY(pointerIndex))){
                 //Move left here
            }

            else if(isRightPressed(event.getX(pointerIndex),event.getY(pointerIndex))){
                //Move right here
            }

                //****These lines randomly fail if the pointerID >=4
                xList[pointerID]=event.getX(pointerIndex);
                yList[pointerID]=event.getY(pointerIndex);

    }
    catch(Exception e){                         
        Log.v("Error","Oops, something's wrong");                   
    }

    break;

    }

}

Почему это? Это ошибка в Multi-touch API или я чего-то не понимаю. При нормальном использовании ошибка обычно не возникает, но я могу легко вызвать ее самостоятельно, и она будет найдена пользователем, поэтому любая помощь будет принята с благодарностью. Я ожидал бы, что любое событие с опущенным пальцем когда-либо получит только ID 0-3. Если я что-то не так понял.

1 ответ

Решение

Не полагайтесь на то, что идентификатор указателя является последовательным или вообще напрямую связан с количеством указателей, которые в данный момент касаются экрана. Идентификатор - это идентификатор, а не способ определить, сколько пальцев опущено или какие пальцы опущены.

В документации говорится, что ID будет просто значением от 0 до getPointerCount() - 1 и что идентификатор используется в конкретном жесте. Таким образом, если Android интерпретирует ваше быстрое нажатие как один жест, несколько нажатий одним пальцем могут иметь разные идентификаторы.

Для вашего конкретного случая это звучит как Map<int, float> может лучше работать для отображения конкретных указателей на их координаты X и Y. Использование карты наверняка исправит ваше исключение.

Например:

Map<Integer, Float> xMap = new HashMap<>();
// ...

case MotionEvent.ACTION_POINTER_DOWN: 
    // ...

    xMap.put(pointerID, event.getX(pointerIndex);

Позже вы можете получить значение, скажем, для указателя с идентификатором 2 с помощью xMap.get(2),

Другие вопросы по тегам