Android 多点触控:ACTION_UP 并不总是被调用?

发布于 2024-11-05 14:45:43 字数 1947 浏览 0 评论 0原文

我开发了一个在视图中处理多点触控的 Android 应用程序。我基本上跟踪可能发生的几个 MotionEvent,例如 ACTION_UP、ACTION_MOVE...我在 View 类中重写的 onTouch 方法如下所示:

public boolean onTouch(View view, MotionEvent event) 
{
    int action = event.getAction() & MotionEvent.ACTION_MASK;

    if (action == MotionEvent.ACTION_DOWN) {
        float x = event.getX();
        handleTouchStart(view, x);
    } else if (action == MotionEvent.ACTION_UP) {
        float x = event.getX();
        handleTouchEnded(view, x);
    } else if (action == MotionEvent.ACTION_POINTER_DOWN) {
        int pointer = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
        float x = event.getX(pointer);
        handleTouchStart(view, x);
    } else if (action == MotionEvent.ACTION_POINTER_UP) {
        int pointer = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
        float x = event.getX(pointer);
        handleTouchEnded(view, x);
    } else if (action == MotionEvent.ACTION_MOVE) {
        int pointer = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
        float x = event.getX(pointer);
        handleTouchMoved(view, x);
    }

    return true;
}

在我的手机(三星 Galaxy S)上,该方法完美运行。对于每个handleTouchStart(),都会调用相应的handleTouchEnded()。这对我的应用程序至关重要。这是一款 2D 横向卷轴游戏,在屏幕左下部分有一个转向区域。如果由于某种原因,当用户从触摸屏上抬起手指时,没有调用 handleTouchEnded() 方法,则玩家的角色会继续运行。

我收到其他设备(如 HTC Desire)上玩家的报告,在极少数情况下,即使他们将手指从屏幕上的转向区域抬起,角色确实会继续朝某个方向奔跑。我的结论是,只有在不调用handleTouchEnded() 的情况下才会发生这种情况,这又意味着不会生成ACTION_UP(或ACTION_POINTER_UP)事件。

是否有特定于设备的多点触控支持实现?是否不能保证对于每个ACTION_DOWN(或ACTION_POINTER_DOWN)MotionEvent,都会调用适当的ACTION_UP(或ACTION_POINTER_UP)MotionEvent?或者我错过了什么?我的 onTouch 实现是否正确?

我更广泛的问题是:是否有更好的方法来处理“动作”游戏的多点触摸屏输入?我基本上是在模仿游戏手柄转向十字的左右控制。我发现 Android 的 UI 按钮没有提供足够的灵活性,因为它们无法跟踪 onPress 和 onRelease 事件……是吗?

I have developed an Android application that is handling multitouch in a view. I basically track the several MotionEvents that can occur like ACTION_UP, ACTION_MOVE, ... My overwritten onTouch method in the View class looks like this:

public boolean onTouch(View view, MotionEvent event) 
{
    int action = event.getAction() & MotionEvent.ACTION_MASK;

    if (action == MotionEvent.ACTION_DOWN) {
        float x = event.getX();
        handleTouchStart(view, x);
    } else if (action == MotionEvent.ACTION_UP) {
        float x = event.getX();
        handleTouchEnded(view, x);
    } else if (action == MotionEvent.ACTION_POINTER_DOWN) {
        int pointer = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
        float x = event.getX(pointer);
        handleTouchStart(view, x);
    } else if (action == MotionEvent.ACTION_POINTER_UP) {
        int pointer = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
        float x = event.getX(pointer);
        handleTouchEnded(view, x);
    } else if (action == MotionEvent.ACTION_MOVE) {
        int pointer = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
        float x = event.getX(pointer);
        handleTouchMoved(view, x);
    }

    return true;
}

On my phone (Samsung Galaxy S), this works flawlessly. For every handleTouchStart(), the appropriate handleTouchEnded() is called. This is crucial for my app. It's a 2D sidescroller with a steering area in the left lower portion of the screen. If - for some reason - the handleTouchEnded() method is not called when the user lifts a finger from the touchscreen, the player's character continues running.

I've received reports from players on other devices (like the HTC Desire) that in rare occasions, the character does indeed continue running in a direction even if they lifted their finger from the steering area on the screen. I concluded that this can only happen if handleTouchEnded() is not called which in turn means that no ACTION_UP (or ACTION_POINTER_UP) event is generated.

Are there device specific implementations of multitouch support? Is there no guarantee that for each ACTION_DOWN (or ACTION_POINTER_DOWN) MotionEvent, an appropriate ACTION_UP (or ACTION_POINTER_UP) MotionEvent is called? Or am I missing something? Is my onTouch implementation even correct?

My broader question would be: are there better ways to handle multitouch touchscreen input for "action"-games? I'm basically mimicking the left and right controls of a gamepad's steering cross. I've found that Android's UI buttons don't offer enough flexibility because they can't track onPress and onRelease events... or do they?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

榆西 2024-11-12 14:45:43

你错过了一些东西。 ;) 您还应该处理另一种操作类型:ACTION_CANCEL。当正在进行的手势在某个更高级别中止时发送 ACTION_CANCEL - 某些更高级别的组件可能已拦截该手势并接管它等。

You're missing something. ;) There is one more action type that you should handle: ACTION_CANCEL. ACTION_CANCEL is sent when the gesture in progress is aborted at some higher level - some higher-level component may have intercepted the gesture and taken it over, etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文