Cathal Comerford
Cathal Comerford

Reputation: 1020

Handle a fling/scroll in Android without consuming the MotionEvent

I've got a ViewFlipper at the side of the screen in my app containing a bunch of different views, and I would like the user to be able to dismiss this by swiping to the left. So I did the usual...

private class SwipeDetector extends SimpleOnGestureListener {

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        //Dismiss view
    }

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }
}

...and then set the onTouchListener of the ViewFlipper to call onTouchEvent in SwipeDetector. It all worked great, however I then noticed because it was consuming all the touch events going into the ViewFlipper, I couldn't click anything when the ViewFlipper itself. If I don't override onDown or I make it return false then the TouchListener ignores the rest of the event and I don't get the fling. I'm happy to hack together some kind of custom swipe detection if I could even handle all the ACTION_MOVE events following the user touching the ViewFlipper but can't even do that. Is there any way to keep listening to the MotionEvent without consuming the onDown?

Upvotes: 5

Views: 3838

Answers (2)

Stefan Reimers
Stefan Reimers

Reputation: 379

Did you notice the GestureDetector? It is available since API Version 1.

http://developer.android.com/reference/android/view/GestureDetector.OnGestureListener.html

Both fling and scroll gestures are handled.

Upvotes: 1

ssantos
ssantos

Reputation: 16536

What works for me is extending View.OnTouchListener instead of SimpleGestureListener, and override onTouch method. Please, take this snippet as a very simple (and improvable) approach to get horizontal swipe detection.-

public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            downX = event.getX();
            return true;
        }
        case MotionEvent.ACTION_UP: {
            upX = event.getX();
            float deltaX = downX - upX;

            if (Math.abs(deltaX) > MIN_DISTANCE) {
                if (deltaX < 0) {
                    this.onLeftToRightSwipe();
                    return true;
                }
                if (deltaX > 0) {
                    this.onRightToLeftSwipe();
                    return true;
                }
                return true;
            }

            return true;
        }
    }
    return false;
}

Upvotes: 2

Related Questions