0

I want to open a dialog whenever a button is getting held down.

This is what I have tried:

// An alter box for a long pressed action
final Handler handler = new Handler();
Runnable mLongPressed = () -> {
    AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
    builder.setTitle("Message");
    builder.setMessage(text);
    builder.show();
};
btn.setOnTouchListener(new OnSwipeTouchListener(getContext()) {
    // Holding a button to show up a message
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
            handler.postDelayed(mLongPressed, ViewConfiguration.getLongPressTimeout());
        }
        if ((motionEvent.getAction() == MotionEvent.ACTION_MOVE) || (motionEvent.getAction() == MotionEvent.ACTION_UP)) {
            handler.removeCallbacks(mLongPressed);
        }
        return super.onTouch(view, motionEvent);
    }

This works fine on my emulator, but not on my actual phone device. Why?

xRay
  • 543
  • 1
  • 5
  • 29
  • 1
    You're probably triggering an `ACTION_MOVE` that's cancelling it. On the emulator, it's relatively easy to keep the mouse pointer still on a single point, but on a physical device, your finger is actually covering several points, and even if you don't move it sideways at all, simply rocking it a bit is enough to trigger an `ACTION_MOVE`. You can put a log print in `onTouch()` to verify. In any case, you'll probably want to implement some sort of touch slop handling there. – Mike M. Aug 01 '22 at 21:27
  • 1
    @MikeM. thanks for this advice! I have now just removed the second if-statement (not sure why I added it) and now it works great! – xRay Aug 01 '22 at 22:03
  • Well, now I see why added it. If I remove the second if-statement, the dialog appears if I hold down the button but it also appears if I simply tap on that button. – xRay Aug 01 '22 at 23:09
  • 1
    You removed it completely? I don't think you don't want to do that. If you just remove the `(motionEvent.getAction() == MotionEvent.ACTION_MOVE)`, it'll still cancel on `ACTION_UP` if it happens before the delay expires, which I think is what you mean to do. – Mike M. Aug 01 '22 at 23:32
  • @MikeM. Yes! Now it works exactly the way I wanted it. Thank you for your help! – xRay Aug 02 '22 at 12:08
  • No problem! Sorry if that comment was confusing. I just realized I messed up editing it, and it's a bit jumbled. Anyhoo, yeah, _that's_ what I thought you meant you were removing, just the `ACTION_MOVE` check. Do note, that will allow the user to move their finger while pressing, but that might be OK for your design. If you do eventually want to handle the `ACTION_MOVE` check – to cancel it, just like a native long-click would – [this dev page](https://developer.android.com/training/gestures/viewgroup#intercept) has an example of how to account for touch slop. Just FYI. Cheers! – Mike M. Aug 02 '22 at 14:32
  • Hang on, that page is not what I thought; the example doesn't really demonstrate how to handle it. I'll see if I can find a better one later on, but in the meantime, you might consider if using a `GestureDetector` would work for your setup; e.g., https://stackoverflow.com/a/7921439. I'm not sure what other interactions you want to handle, but `GestureDetector` does the long-click timing and touch slop calculations automatically, so it'd be much easier to use, unless you need some really specialized event handling. – Mike M. Aug 02 '22 at 14:53
  • 1
    @MikeM. oh, I didn't know about `GestureDetector`. This may be a much better solution for my case. Thanks for this info! Very useful. – xRay Aug 02 '22 at 16:37

0 Answers0