7

I have a UX requirement that the user triggers a Dialog by long pressing a cell in a GridView.

  • While the Dialog is displayed the user must be able to move their finger/thumb around the screen without triggering the UP/CANCEL event when they leave the bounds of GridView cell.

  • When the user finally breaks contact with the screen is what I'm looking to capture. GridView seems to register some false positives for UP/CANCEL that we don't see using any other views.

  • The issue is that the original view captures all the touch events because the DOWN was captured by it.

  • The dialog registers/sees no touches until after the UP event from the original view.

I have tried cancelling the original touch event and using dispatchTouch(), etc. No joy.

Any ideas?

AZ_
  • 21,688
  • 25
  • 143
  • 191
Bill Mote
  • 12,644
  • 7
  • 58
  • 82
  • Could you be more specific? i don't understand what you want to do. – MineConsulting SRL Oct 30 '14 at 10:15
  • Have a view in an activity or fragment trigger the display of a dialog when the view is longpressed (working). The user must be able to move their finger off the view that triggered the dialog, but never break contact with the screen. When, and only when, the user breaks contact with the screen trigger another event. Issue: when moving outside the bounds of the original view ACTION_UP and/or ACTION_CANCEL are triggered and no touches are registered by the dialog (or anything else) until the user breaks contact with the screen and retouches. – Bill Mote Oct 30 '14 at 20:23
  • I have done something similar without grid view. User has to long press a dialog will appear user can move his finger (while pressing) everywhere and when user pick up the finger dialog gets hidden. Please consider making a video and post it here. I didn't understand this part (and no touches are registered by the dialog (or anything else) until the user breaks contact with the screen and retouches. ) – AZ_ Oct 31 '14 at 06:56
  • Since app is underdevelopment I cannot give you a demo :/ – AZ_ Oct 31 '14 at 06:57
  • 1
    If your problem is that the previous view is capturing all the future touch events it's because it has maintained a list of touch events. I would recommend you to see the source code. – AZ_ Oct 31 '14 at 07:06
  • I will have to gen up an example as I can't use this project's code publicly. – Bill Mote Oct 31 '14 at 19:22

1 Answers1

2

I have used something like this in one of my projects.

Assign an OnTouchListener to every cell of your gridView and override the OnTouch method.

@Override
public boolean onTouch(View v, MotionEvent event) {

boolean isLongPressed;

int mSwipeSlop = ViewConfiguration.get(context).
                getScaledTouchSlop();

boolean mSwiping;

switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        handler.postDelayed(mLongPressed, 1000);
        break;

    case MotionEvent.ACTION_CANCEL:
        handler.removeCallbacks(mLongPressed);
        break;

    case MotionEvent.ACTION_MOVE:
        float x = event.getX() + v.getTranslationX();
            float deltaX = x - mDownX;
            float deltaXAbs = Math.abs(deltaX);
            float y = event.getY() + v.getTranslationY();
            float deltaY = Y - mDownY;
            float deltaYAbs = Math.abs(deltaY);
            float absDist = Math.sqrt(Math.pow(deltaXAbs, 2) + Math.pow(deltaXAbs, 2));
            if (!mSwiping) {
                if (absDist > mSwipeSlop) {
                    mSwiping = true;
                    handler.removeCallbacks(mLongPressed);
                }
            }
        break;

    case MotionEvent.ACTION_UP:
        handler.removeCallbacks(mLongPressed);
        if (isLongPressed) {
             // DO ACTION UP
        }
        break;

    default: 
        return false;
    }
return true;
}

Open the dialog in the runnable mLongPressed, which will only run if the user has touched the same spot for a second. You can change the distance he can move and the time he needs to press to register as a long click of course. However, I would recommend using getScaledTouchSlop() for the distance.

final Handler handler = new Handler(); 
Runnable mLongPressed = new Runnable() { 
    public void run() { 
        // OPEN DIALOG
        isLongPressed = true;
    }   
};

By using this code in my project, the user can move his finger around the whole screen without ACTION_UP getting triggered. Only when he lifts his finger, it is triggered.

Robbe
  • 2,610
  • 1
  • 20
  • 31