2

因此,简单地说,我用于多点触控的处理程序会崩溃并抛出“IllegalArgumentException:pointerIndex out of range”。

我试着捕捉错误,但后来意识到 (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 是否超出当前pointerCount 的范围,如果超出,我至少可以用两行代码解决两个手指的问题。

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

我不确定这是否真的解决了这个问题,但它似乎适用于两指多点触控控制,例如用于触摸屏 fps 游戏的控制。我自己的测试表明,它能够准确无误地确定两个点的触摸,并存储正确的 (x, y) 值

有没有更好的解决方案,或者指针 ID 的多点触控 API 使用真的那么糟糕?如果有人想知道,这是在 4.0.3 设备上。

4

1 回答 1

0

对我来说,您使用 pointerId 作为参数访问 event.getX() 和 event.getY() 似乎很奇怪(在 ACTION_POINTER_DOWN 处)。我认为它应该是指针索引,就像你在所有其他情况下所做的那样。

于 2014-06-01T07:47:43.033 回答