0

I'm making video stories like instagram. So I met a problem with gestures.

The problem is that ACTION_CANCEL handled when I'm doing these moves and ACTION_UP doesn't call if I raise my finger

  1. I'm in 1st page of ViewPager and I swipe left->right fastly (my finger still on screen)
  2. I'm in the middle of ViewPager and I swipe left->right or right->left, but not finishing the swipe and I'm still in the current page and my finger on screen
  3. I'm moving chaosly on screen (my finger still on screen)

So if I raise my finger after ACTION_CANCEL called, my video stay in "PAUSE" state

Finally, question is: How I can handle Action_Up event after Action_Cancel?

override fun onTouch(v: View?, event: MotionEvent?): Boolean {
    if (gestureDetector?.onTouchEvent(event) == true) return true

    when (event?.actionMasked) {
        MotionEvent.ACTION_DOWN -> {
            viewModel.videoPause()
        }
        MotionEvent.ACTION_UP -> {
            viewModel.videoResume()
        }
        MotionEvent.ACTION_CANCEL -> {
            // Handles when doing these moves and ACTION_UP doesn't call if I raise my finger
            // 1. I'm in 1st page of ViewPager and I swipe left->right fastly (my finger still on screen)
            // 2. I'm in the middle of ViewPager and I swipe left->right or right->left, but not finishing the swipe
            // and I'm still in the current page and my finger on screen
            // 3. I'm moving chaosly on screen (my finger still on screen)


            // So if I raise my finger after ACTION_CANCEL called, my video stay in "PAUSE" state
        }
        else -> { }
    }

    return true
}

user stories 1st page user stories swipe

2 Answers2

1

You don't get an ACTION_UP after an ACTION_CANCEL:

ACTION_CANCEL

public static final int ACTION_CANCEL

Constant for getActionMasked(): 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.

cactustictacs
  • 17,935
  • 2
  • 14
  • 25
  • Yes, I know that, but is any other way to handle actionUp after actionCancel? Because my finger is still on screen and when I raise my finger nothing handles – Nursultan Almakhanov May 13 '22 at 07:12
  • @NursultanAlmakhanov it's saying that when you get ``ACTION_CANCEL``, that's it - you get no other events for that gesture, including `ACTION_UP`. Like it says, *"you should treat this as an up event"* - it's another *kind* of ``ACTION_UP`` but one where you should treat the gesture as cancelled instead of completed. So in your case, if you're pausing when the user puts their finger down, and unpausing when they lift it up (`ACTION_UP`), seems like you'd probably want to unpause when it's cancelled too? So it's only paused while the user's touching the video – cactustictacs May 13 '22 at 18:00
  • I want to unpause it when user lifts up the finger, not on actionCancel. But I temporarily set unpause on actionCancel and looking for other solutions. – Nursultan Almakhanov May 15 '22 at 12:39
  • 1
    @NursultanAlmakhanov that's not how it works - a gesture *starts* with an `ACTION_DOWN` event, and ends with *either* an `ACTION_UP` **or** an `ACTION_CANCEL`, depending on how the gesture was terminated (e.g. lifting the finger vs moving outside of the view). It doesn't matter if your finger is still touching the screen - the moment you get `ACTION_CANCEL`, the gesture is *finished* and you won't get any more events for it (so you can't tell when the finger is lifted). If you want to avoid gestures being cancelled at all, there's some approaches here: https://stackoverflow.com/q/6018309 – cactustictacs May 15 '22 at 17:20
1

Actually there is a way to do this.

@Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        performClick();
        switch (event.getAction()){
            case MotionEvent.ACTION_MOVE:
                float x = event.getX();
                float y = event.getY();
                Log.d("coordinates: ","x : "+String.valueOf(x)+"y : " + String.valueOf(y));
                break;
            case MotionEvent.ACTION_UP:
                Log.d("action","up")
        }
        return true;
    }

Add this to your parent View. This will show you the location of your finger whenever it moves. And (I don't know how) but when you hold your finger, it also triggers the action up. So whenever the action up is triggered, you'll know that the user held his finger, or whenever the x or y coordinates are outside of your parent view, you can treat it as if the user held his finger. (I got this idea from a canvas question [https://stackoverflow.com/questions/21846584/android-canvas-draw-by-finger])