了解Android PointerID。回归意外的价值

时间:2014-12-25 18:51:16

标签: android multi-touch indexoutofboundsexception actionevent ontouch

我最近收到了针对我的应用程序的崩溃报告,在查看了堆栈跟踪后,意识到我的多点触控控件存在问题。

发生的事情是这样的:

我正试图记录仅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.............

因此,如果手指超过4个,我就不会在onTouch中运行任何东西。

这似乎工作正常,它通常不会对手指5,6等“行动”。所以那里一切都很好。 (我说'一般'因为下面的内容).....

问题

然而,如果我说下,6个手指向下,然后将它们抬起,放下的最后一个手指的指针ID为5.这不是一个真正的问题因为我在 action_up <中没有做任何事情/ em>或 action_pointer_up

action_pointer_down 中,90%的时间我得到预期的行为,其中任何一个手指放下的ID都只有0到3之间。

但是,如果您在屏幕上放置5个或更多手指并反复快速点击屏幕,最终会将ID分配给 action_pointer_down 事件,是4或更多(我见过4,5,6和7)所以当它试图将这些值放入xList nad yList数组时,它会以越界异常崩溃。

这是一个问题,因为在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;

    }

}

这是为什么?这是Multi-touch API中的错误还是我不理解的东西。在正常使用中,错误通常不会发生,但我可以自己轻松触发它并由用户找到它,因此任何帮助都将受到赞赏。我希望任何手指向下事件只能获得0-3的ID。除非我误解了什么。

1 个答案:

答案 0 :(得分:1)

不要依赖指针的ID是顺序的,或者根本与当前触摸屏幕的指针数量直接相关。 ID是一个标识符,不是识别手指向下或手指向下的方式。

The documentation表示ID只是介于0和getPointerCount() - 1之间的值,并且ID在特定手势中使用。因此,如果Android将您的快速点击解释为单个手势,则使用相同手指的多个点击可能会有不同的ID。

对于您的特定情况,听起来Map<int, float>可能更适合将特定指针映射到其X和Y坐标。使用地图肯定会修复你的越界异常。

例如:

Map<Integer, Float> xMap = new HashMap<>();
// ...

case MotionEvent.ACTION_POINTER_DOWN: 
    // ...

    xMap.put(pointerID, event.getX(pointerIndex);

稍后您可以使用xMap.get(2)检索ID为2的指针的值。