Итак, обработчик, который я использовал для мультитач, разбился бы и выкинул «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.
Что вы хотите сказать? – slayton
Есть ли лучший способ решить эту проблему? Например, есть ли основная проблема с моим кодом? Или это ошибка во всем мультитач-коде, который только обходной путь вроде этого «исправляет»? – cavemaneca