最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

android - ACTION_CANCELACTION_UP not triggered after ACTION_DOWN - Stack Overflow

programmeradmin0浏览0评论

On Android, touch events usually come in ACTION_DOWN and ACTION_UP pairs. Sometimes, you receive ACTION_CANCEL instead of the ACTION_UP event. Thus, always a pair of events which makes perfect sense.

Now, after 13 years of Android app development, I found a simple way to end up with an ACTION_DOWN which never results in the expected ACTION_UP or ACTION_CANCEL event. In our game, this bug means the game recognizes an eternal touch down. Not ideal for touch based games...

Steps to reproduce

Use a modern device with system gestures, like Pixel 9 Pro.

  1. Create a new "Empty Views Activity" in Android Studio. Choose Java.
  2. Override onTouchEvent as shown below.
  3. Start navigation gesture from the right side.
  4. When the "navigate" arrow appears, swipe back to the right side. The arrow disappears. Release your finger.
@Override
public boolean onTouchEvent(MotionEvent event) {
    String s = MotionEvent.actionToString((event.getAction()));
    Log.d("TOUCH", s);

    return super.onTouchEvent(event);
}

If you successfully canceled the system gesture, you will only see ACTION_DOWN (and possibly some ACTION_MOVE) in the log.

Since Google refuse to recognize issues/401872146 I'm turning to the community. Is this expected behavior? Not sure how to interpret the rather ambiguous MotionEvent Consistency Guarantees.

Canceling a system gesture (starting with ACTION_DOWN) should produce a corresponding ACTION_UP or ACTION_CANCEL. It does not happen.

On Android, touch events usually come in ACTION_DOWN and ACTION_UP pairs. Sometimes, you receive ACTION_CANCEL instead of the ACTION_UP event. Thus, always a pair of events which makes perfect sense.

Now, after 13 years of Android app development, I found a simple way to end up with an ACTION_DOWN which never results in the expected ACTION_UP or ACTION_CANCEL event. In our game, this bug means the game recognizes an eternal touch down. Not ideal for touch based games...

Steps to reproduce

Use a modern device with system gestures, like Pixel 9 Pro.

  1. Create a new "Empty Views Activity" in Android Studio. Choose Java.
  2. Override onTouchEvent as shown below.
  3. Start navigation gesture from the right side.
  4. When the "navigate" arrow appears, swipe back to the right side. The arrow disappears. Release your finger.
@Override
public boolean onTouchEvent(MotionEvent event) {
    String s = MotionEvent.actionToString((event.getAction()));
    Log.d("TOUCH", s);

    return super.onTouchEvent(event);
}

If you successfully canceled the system gesture, you will only see ACTION_DOWN (and possibly some ACTION_MOVE) in the log.

Since Google refuse to recognize issues/401872146 I'm turning to the community. Is this expected behavior? Not sure how to interpret the rather ambiguous MotionEvent Consistency Guarantees.

Canceling a system gesture (starting with ACTION_DOWN) should produce a corresponding ACTION_UP or ACTION_CANCEL. It does not happen.

Share Improve this question asked Mar 11 at 20:02 l33tl33t 20k19 gold badges112 silver badges190 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

I guess the intended solution is to ignore events intersecting the system gesture insets.
For me, not getting an ACTION_CANCEL was very unexpected as well. This unnecessarily breaks old code, which would otherwise be working perfectly fine, since ACTION_CANCEL would signal exactly the right thing:

The current gesture has been aborted. You will not receive any more points in it. You should treat this as an up event, but not perform any action that you normally would.

Instead of this straight forward solution, every developer now needs to implement additional logic.

I interpret the consistency guarantees as "there are no guarantees":

Views should always be prepared to handle ACTION_CANCEL and should tolerate anomalous situations such as receiving a new ACTION_DOWN without first having received an ACTION_UP for the prior gesture.

But other parts of the documentation imply that every ACTION_DOWN ends with ACTION_UP or ACTION_CANCEL, e.g.:

Each pointer has a unique id that is assigned when it first goes down (indicated by ACTION_DOWN or ACTION_POINTER_DOWN). A pointer id remains valid until the pointer eventually goes up (indicated by ACTION_UP or ACTION_POINTER_UP) or when the gesture is canceled (indicated by ACTION_CANCEL).

发布评论

评论列表(0)

  1. 暂无评论