2012-04-04 2 views
2

Итак, обработчик, который я использовал для мультитач, разбился бы и выкинул «IllegalArgumentException: pointerIndex вне диапазона».Android: Получение правильного pointerId для приложений multiTouch на android

Я попытался просто поймать ошибку, но потом понял, что (x, y) будет по умолчанию (min.x, max.y), который был (0,0, 480,0) в моем случае.

После того, как я немного побеспокоился, я обнаружил, что ошибка появилась только при спаме, но может быть специально и очень регулярно воспроизведена просто путем поочередного нажатия в двух разных местах достаточно быстро (но все же достаточно медленно, чтобы произойти во время обычная мультитач-игра).

Вот метод onTouch:

public boolean onTouch(View v, MotionEvent event) { 
    synchronized (this) { 
     int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 
     int pointerId = event.getPointerId(pointerIndex); 
     TouchEvent touchEvent; 

     // pointerId fix 
     if (pointerId >= event.getPointerCount() && pointerId > 0) 
      pointerId--; 

     switch (event.getAction() & MotionEvent.ACTION_MASK) { 
     case MotionEvent.ACTION_DOWN: 
     case MotionEvent.ACTION_POINTER_DOWN: 
      touchEvent = touchEventPool.newObject(); 
      touchEvent.type = TouchEvent.TOUCH_DOWN; 
      touchEvent.pointer = pointerId; 
      try { 
       touchEvent.x = touchX[pointerId] = (int) (event 
         .getX(pointerId) * scaleX); 
       touchEvent.y = touchY[pointerId] = (int) (event 
         .getY(pointerId) * scaleY); 
      } catch (IllegalArgumentException e) { 
       Log.d("multiTouchHandler", e.toString() + ":: PID = " 
         + pointerId); 
      } 
      isTouched[pointerId] = true; 
      touchEventsBuffer.add(touchEvent); 
      break; 

     case MotionEvent.ACTION_UP: 
     case MotionEvent.ACTION_POINTER_UP: 
      touchEvent = touchEventPool.newObject(); 
      touchEvent.type = TouchEvent.TOUCH_UP; 
      touchEvent.pointer = pointerId; 

      try { 
       touchEvent.x = touchX[pointerId] = (int) (event 
         .getX(pointerIndex) * scaleX); 
       touchEvent.y = touchY[pointerId] = (int) (event 
         .getY(pointerIndex) * scaleY); 
      } catch (IllegalArgumentException e) { 
       Log.d("multiTouchHandler", e.toString() + ":: PID = " 
         + pointerId); 
      } 
      isTouched[pointerId] = false; 
      touchEventsBuffer.add(touchEvent); 
      return false; 

     case MotionEvent.ACTION_MOVE: 
      int pointerCount = event.getPointerCount(); 
      for (int i = 0; i < pointerCount; i++) { 
       touchEvent = touchEventPool.newObject(); 
       touchEvent.type = TouchEvent.TOUCH_DRAGGED; 
       touchEvent.pointer = pointerId; 
       try { 
        touchEvent.x = touchX[pointerId] = (int) (event 
          .getX(pointerIndex) * scaleX); 
        touchEvent.y = touchY[pointerId] = (int) (event 
          .getY(pointerIndex) * scaleY); 
       } catch (IllegalArgumentException e) { 
        Log.d("multiTouchHandler", e.toString() + ":: PID = " 
          + pointerId); 
       } 
       isTouched[pointerId] = false; 
       touchEventsBuffer.add(touchEvent); 
      } 
      break; 
     case MotionEvent.ACTION_CANCEL: 
     } 
     return true; 
    } 
} 

Что это, казалось, происходило с выхода Log.d было, что иногда pointerId бы получить назначены на следующий доступный указатель (например, 1.), Но на самом деле указатель данные будут храниться в предыдущем местоположении указателя (0).

Проверяя, был ли pointerId вне диапазона текущего указателя, и если он вернется назад, я смог хотя бы исправить эту проблему для двух пальцев с двумя строками кода.

// pointerId fix 
if (pointerId >= event.getPointerCount() && pointerId > 0) 
       pointerId--; 

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

Есть ли лучшее решение, или использование API-интерфейсов мультитач API-идентификаторов это плохо? Если кто-то хочет знать, это было на устройстве 4.0.3.

+0

Что вы хотите сказать? – slayton

+0

Есть ли лучший способ решить эту проблему? Например, есть ли основная проблема с моим кодом? Или это ошибка во всем мультитач-коде, который только обходной путь вроде этого «исправляет»? – cavemaneca

ответ

0

Мне кажется странным, что вы получаете доступ к event.getX() и event.getY() с помощью pointerId в качестве аргумента (в ACTION_POINTER_DOWN). Я думаю, что вместо этого он должен быть pointerIndex, как и во всех остальных случаях.

Смежные вопросы