1

Недавно я получил отчет о сбоях для своего приложения и, посмотрев на трассировку стека, понял, что у меня проблема с элементами управления с несколькими касаниями.Понимание 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 пальцы вниз, затем поднимите их вверх, последний палец помещается вниз еще идентификатор pointerID 5. Это не проблема, поскольку я ничего не делаю в action_up или action_pointer_up.

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

Однако, если вы поместите 5 или больше пальцев на экране и быстро коснитесь экрана снова и снова, в конце концов, идентификатор будет присвоен значению action_pointer_down, которое равно 4 или более (я видел 4, 5, 6 & 7) Поэтому, когда он пытается поместите эти значения в массивы xList nad yList, он выйдет из строя с за пределами e xception.

Это проблема, потому что в 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; 

    } 

} 

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

ответ

1

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

The documentation утверждает, что идентификатор будет просто значением от 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).

+0

Hi @ Tania.7x - спасибо. Понимаю. Не могли бы вы привести пример использования карты? Также вы можете увидеть решение, в котором я могу использовать заранее определенный массив? Я говорю это, потому что, как я понимаю, Map использует итератор и выделяет память, когда к нему обращаются. Спасибо за вашу помощь!! – Zippy

+0

Обычно вы не перебираете карту, хотя, конечно, можете, если хотите. Карта полезна, когда у вас есть элементы с определенным ключом (например, ID), но у вас нет гарантии, что эти ключи будут в каком-либо конкретном порядке или не будут последовательными. –