Android MotionEvent指针索引混乱
Android MotionEvent Pointer Index Confusion
我的 Android 应用程序有问题,需要触摸跟踪事件(跟踪 when/where 手指向下、移动、向上等)。我必须使用 event.getX()
和 event.getY()
函数来获取当前触摸的坐标。
所以根据我在过去几个月中学到的知识:
MotionEvent.ACTION_DOWN
跟踪第一次触地
MotionEvent.ACTION_POINTER_DOWN
跟踪后续触地得分
MotionEvent.ACTION_UP
跟踪最后一次修饰
MotionEvent.ACTION_POINTER_UP
跟踪上升的触摸
MotionEvent.ACTION_MOVE
跟踪任何触摸动作
在我的应用程序中,当我第一次触摸时,我遇到了一个严重的问题。假设我有五个手指在触摸我的设备(我们称它们为 Touch 0、1、2、3、4)。现在,当我抬起 Touch 0 时,MotionEvent.ACTION_POINTER_UP
是我得到的动作。完全可以理解;我明白了。但是,现在会发生这两件事:
- 从 Touches 1-4 移动任何内容:得到一个
IllegalArgumentException
告诉我 pointerIndex 超出范围
- 从 Touches 1-4 举起任何东西:吐回不同触摸的信息(
event.getX()
和 event.getY()
会给我不同的手指信息)
对于如何正确跟踪此信息,我有点不知所措。关于如何正确跟踪信息或偏移触摸指针的任何线索?
我提供了我的代码的总体布局,但我觉得我没有做任何不寻常的事情(而且我确信它接近 Android 示例中的示例代码?):
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getActionMasked();
int ptr_idx = event.getPointerId(event.getActionIndex());
try {
switch (action) {
case MotionEvent.ACTION_MOVE:
handleActionPointerMove(event);
break;
// Order of touch downs doesn't matter to us
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
handleActionPointerDown(event, ptr_idx);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
handleActionPointerUp(event, ptr_idx);
break;
}
}
catch (IllegalArgumentException e) {
e.printStackTrace();
return false;
}
return true;
}
}
public void handleActionPointerMove(MotionEvent event) {
for (int i = 0; i < event.getPointerCount(); i++) {
handleInformation(event.getX(i), event.getY(i));
}
}
public void handleActionPointerDown(MotionEvent event, int ptr_idx) {
handleInformation(event.getX(ptr_idx), event.getY(ptr_idx));
}
public void handleActionPointerUp(MotionEvent event, int ptr_idx) {
handleInformation(event.getX(ptr_idx), event.getY(ptr_idx));
}
public void handleInformation(int x, int y) {
// Figures out what x+y means to us (are we in a certain box within the app? outside in clear zones? etc
}
好吧,考虑了一个晚上之后,我在调用 MotionEvent.getX()
和 MotionEvent.getY()
:
之前开始做这件事
public int getAdjustment(int ptr_idx) {
int adjust = 0;
for (int i = 0; i < event.getPointerCount(); i++) {
// Get Actual Pointer Index of touch
int adjustedPointerIndex = event.getPointerId(i);
// If we've found the current touch's pointer index AND
// the pointer index doesn't equal the sequential event's
// pointers
if ((adjustPointerIndex == ptr_idx) && (i != adjustPointerIndex)) {
adjust = (adjustPointerIndex - i);
break;
}
}
return adjust;
}
// Example Function using getAdjustment(int ptr_idx)
public void handleActionPointerUp(MotionEvent event, int ptr_idx) {
int adjustment = ptr_idx - getAdjustment(ptr_idx);
handleInformation(event.getX(adjustment), event.getY(adjustment));
}
for循环语句的解释:
基本上,假设我们有 4 次触摸(触摸 0、1、2、3)。现在我们已经抬起 Touch 0,现在我们有 Touch 1、2、3。Android 会将这些触摸视为 0、1、2,实际指针索引为 1、2、3。要获得正确的调整,我遍历 MotionEvent
的指针(这是 for 循环中现在的 0、1、2)。
现在,如果由于某种原因触摸 0 或之间的任何触摸被取出,我们必须调整指针索引,因为 getX()
并且 getY()
不了解触摸的实际指针索引。它只接受索引 0、1、2,即使我们有指针索引 1、2、3。因此,如果我们已经达到正确的当前触摸指针索引,但 MotionEvent
的触摸索引不等于正确触摸指针索引,我们通过adjust = adjustPointerIndex-i
来调整它。
这样做之后,只需从我们正在分析的当前 ptr_idx
中减去它,我们就会得到 getX()
和 getY()
可以理解的值,而无需 IllegalArgumentException
pointerIndex 超出范围。
如果这没有意义,将进行更彻底的解释,如果有人有更优雅的解决方案,请告诉我,因为我确信这不是处理此问题的好方法。我宁愿将别人的答案标记为已批准的答案。
我的 Android 应用程序有问题,需要触摸跟踪事件(跟踪 when/where 手指向下、移动、向上等)。我必须使用 event.getX()
和 event.getY()
函数来获取当前触摸的坐标。
所以根据我在过去几个月中学到的知识:
MotionEvent.ACTION_DOWN
跟踪第一次触地MotionEvent.ACTION_POINTER_DOWN
跟踪后续触地得分MotionEvent.ACTION_UP
跟踪最后一次修饰MotionEvent.ACTION_POINTER_UP
跟踪上升的触摸MotionEvent.ACTION_MOVE
跟踪任何触摸动作
在我的应用程序中,当我第一次触摸时,我遇到了一个严重的问题。假设我有五个手指在触摸我的设备(我们称它们为 Touch 0、1、2、3、4)。现在,当我抬起 Touch 0 时,MotionEvent.ACTION_POINTER_UP
是我得到的动作。完全可以理解;我明白了。但是,现在会发生这两件事:
- 从 Touches 1-4 移动任何内容:得到一个
IllegalArgumentException
告诉我 pointerIndex 超出范围 - 从 Touches 1-4 举起任何东西:吐回不同触摸的信息(
event.getX()
和event.getY()
会给我不同的手指信息)
对于如何正确跟踪此信息,我有点不知所措。关于如何正确跟踪信息或偏移触摸指针的任何线索?
我提供了我的代码的总体布局,但我觉得我没有做任何不寻常的事情(而且我确信它接近 Android 示例中的示例代码?):
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getActionMasked();
int ptr_idx = event.getPointerId(event.getActionIndex());
try {
switch (action) {
case MotionEvent.ACTION_MOVE:
handleActionPointerMove(event);
break;
// Order of touch downs doesn't matter to us
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
handleActionPointerDown(event, ptr_idx);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
handleActionPointerUp(event, ptr_idx);
break;
}
}
catch (IllegalArgumentException e) {
e.printStackTrace();
return false;
}
return true;
}
}
public void handleActionPointerMove(MotionEvent event) {
for (int i = 0; i < event.getPointerCount(); i++) {
handleInformation(event.getX(i), event.getY(i));
}
}
public void handleActionPointerDown(MotionEvent event, int ptr_idx) {
handleInformation(event.getX(ptr_idx), event.getY(ptr_idx));
}
public void handleActionPointerUp(MotionEvent event, int ptr_idx) {
handleInformation(event.getX(ptr_idx), event.getY(ptr_idx));
}
public void handleInformation(int x, int y) {
// Figures out what x+y means to us (are we in a certain box within the app? outside in clear zones? etc
}
好吧,考虑了一个晚上之后,我在调用 MotionEvent.getX()
和 MotionEvent.getY()
:
public int getAdjustment(int ptr_idx) {
int adjust = 0;
for (int i = 0; i < event.getPointerCount(); i++) {
// Get Actual Pointer Index of touch
int adjustedPointerIndex = event.getPointerId(i);
// If we've found the current touch's pointer index AND
// the pointer index doesn't equal the sequential event's
// pointers
if ((adjustPointerIndex == ptr_idx) && (i != adjustPointerIndex)) {
adjust = (adjustPointerIndex - i);
break;
}
}
return adjust;
}
// Example Function using getAdjustment(int ptr_idx)
public void handleActionPointerUp(MotionEvent event, int ptr_idx) {
int adjustment = ptr_idx - getAdjustment(ptr_idx);
handleInformation(event.getX(adjustment), event.getY(adjustment));
}
for循环语句的解释:
基本上,假设我们有 4 次触摸(触摸 0、1、2、3)。现在我们已经抬起 Touch 0,现在我们有 Touch 1、2、3。Android 会将这些触摸视为 0、1、2,实际指针索引为 1、2、3。要获得正确的调整,我遍历 MotionEvent
的指针(这是 for 循环中现在的 0、1、2)。
现在,如果由于某种原因触摸 0 或之间的任何触摸被取出,我们必须调整指针索引,因为 getX()
并且 getY()
不了解触摸的实际指针索引。它只接受索引 0、1、2,即使我们有指针索引 1、2、3。因此,如果我们已经达到正确的当前触摸指针索引,但 MotionEvent
的触摸索引不等于正确触摸指针索引,我们通过adjust = adjustPointerIndex-i
来调整它。
这样做之后,只需从我们正在分析的当前 ptr_idx
中减去它,我们就会得到 getX()
和 getY()
可以理解的值,而无需 IllegalArgumentException
pointerIndex 超出范围。
如果这没有意义,将进行更彻底的解释,如果有人有更优雅的解决方案,请告诉我,因为我确信这不是处理此问题的好方法。我宁愿将别人的答案标记为已批准的答案。