PointerIndex вне диапазона Android multitouch

У меня есть исключение события касания, которое приводит к сбою моей игры на планшетах (или, более конкретно, сотовых)... Моя игра отлично работает на моем телефоне, и я не слышал об этом, происходящем с кем-либо, работает под управлением Android 3.0 или выше. Вот соответствующая информация журнала...

E/AndroidRuntime(26487): java.lang.IllegalArgumentException: pointerIndex out of range
E/AndroidRuntime(26487):    at android.view.MotionEvent.nativeGetAxisValue(Native Method)
E/AndroidRuntime(26487):    at android.view.MotionEvent.getX(MotionEvent.java:1549)
E/AndroidRuntime(26487):    at kieran.android.asteroids.GameUI.onTouchEvent(GameUI.java:665)
E/AndroidRuntime(26487):    at android.view.View.dispatchTouchEvent(View.java:4616)
E/AndroidRuntime(26487):    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560)
E/AndroidRuntime(26487):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1291)
E/AndroidRuntime(26487):    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560)
E/AndroidRuntime(26487):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1291)
E/AndroidRuntime(26487):    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560)
E/AndroidRuntime(26487):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1291)

... И вот код, который его вызывает. Кажется хорошо для меня, но, может быть, в сотах есть ошибка, которая еще не исправлена? Номер строки 665 из журнала выше соответствует строке float x = event.getX(id);. Должно быть, это связано с тем, как я могу получить переменную which, возможно? Но он отлично работает на телефонах /2.3 и ниже...

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

if(actionCode == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_UP) {
    int which = action >> MotionEvent.ACTION_POINTER_ID_SHIFT;
    int id = event.getPointerId(which);
    float x = event.getX(id);
    float y = event.getY(id);

Любая помощь/идеи были бы очень благодарны, поскольку я пытаюсь сделать свою игру доступной для пользователей планшетов. Спасибо.

Ответ 1

Моя проблема заключалась в том, что на самом деле он вызывал event.getX(1), когда на самом деле не было двух идентификаторов. Поэтому я убедился, что есть два идентификатора с event.getPointerCount() >= 2, и теперь он работает. Возможно, у вас будет такая же удача!

Ответ 2

Пропуская несколько вещей, вам нужно применить маску к указателю в противном случае, поскольку вы не получаете технически доступ к идентификатору пальца, который, по вашему мнению, вы

int action = event.getAction() & MotionEvent.ACTION_MASK;     
int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
int pointerId = event.getPointerId(pointerIndex);

Ответ 3

У меня также есть эта ошибка, но ни одно из решений до даты моего сообщения не работает. Единственное временное псевдо-исправление, которое работает для меня, - использовать try-catch для исключения IllegalArgumentException.

Согласно Android Issue 18990, это связано с ScaleGestureDetector, и исправление было совершено несколько дней назад.

Ответ 4

Исходная публикация использует идентификатор указателя, когда getX и getY используют указатель указателя.

Он работает, когда вы используете идентификатор для одного касания, потому что идентификатор и индекс равны 0. Это испортит, если вы используете мультитач, потому что индексы могут меняться.

Пример:

Нажмите 1 вниз.
Нажмите 1 Индекс состояния = 0. ID = 0

Коснитесь 2 вниз.
Нажмите 1 Индекс состояния = 0. ID = 0
Коснитесь 2 Состояние Индекс = 1. ID = 1

Нажмите 1 релиз.
Коснитесь 2 Состояние Индекс = 0. ID = 1

Попробуйте использовать следующий код:

final int action = e.getAction();       
final int pointerIndex =(action & MotionEvent.ACTION_POINTER_INDEX_MASK) 
                >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;      
float x = event.getX(pointerIndex);
float y = event.getY(pointerIndex);

Ответ 5

Просто измените getPointerId() на findPointerIndex(). Возможно, измените geAction() на getActionMasked().

Надеюсь, что это поможет!