user2436032
user2436032

Reputation: 365

How to detect View pager vertical swipe and send that event to the layout below ?

I have one view that has some vertical gestures like swipe down to move the view down etc. lets call this View rootView. Everything was good util I needed to add a view pager on top of it. Now the ViewPager is consuming all the touch events. The ViewPager is scrolling horizontally as it should, but consuming the vertical swipes too and doing nothing (not passing the event to the rootView). How to make both the Views listen to their corresponding touch events and send the rest to other. I tried creating a CustomViewPager and overriding its onTouchEvent in the hope of recognizing the swipe down first and return false in that case so that the rootview will get a chance to handle that touch event. But in the process of recognizing the gesture as down/up , the ViewPager is consuming ACTION_DOWN and ACTION_MOVE event which are needed by the rootView to process the amount of finger movement.

A solution that came to my mind is to add onTouchEvent on all the layout over the ViewPager, which recognize the Vertical vs horizontal and call the appropriate touchevent (of rootView vs ViewPager) , but in order to recognize the up/down/side gesture, the layout will consume some events which may be valueable to the rootView.

Another solution that comes to mind is to override the ontouchEvent of ViewPager and call the onTouchEvent of the rootView irrespective of the up/down/side movement. In this way both the ViewPager and rootView can use the event, but it is sometimes making the screen fluctuates.

How should I solve this problem ? I would appreciate some suggestions, and no need to provide the code, just a good way to solve this problem.

Upvotes: 2

Views: 2207

Answers (2)

Eric B.
Eric B.

Reputation: 703

I've had to completely modify my original answer. My first solution was to subclass ViewPager and override onTouchEvent(), adding logic to switch between the CustomViewPager and the RelativeLayout below it. Returning false means the view ignores the event, and returning super.onTouchEvent(event) means the view consumes the event until the user lifts their finger. All the logic was in the ACTION_MOVE part of the event, but since you only get one chance to return a value (which is the first part of the event, ACTION_DOWN), you can't use any movement to determine whether to consume or ignore the event.

I finally got it to work by writing an entirely new class, starting with the ViewPager code and adding logic to recognize vertical gestures. When a vertical gesture occurs, code is run that acts on the RelativeLayout below it, instead of passing the touch event to it. Below is a code snippet from the onTouchEvent() of my class.

public class CustomViewPager extends ViewGroup {

    // code from ViewPager class...

    case MotionEvent.ACTION_MOVE:
            if (!mIsBeingDragged) {
                if (DEBUG) Log.v(TAG, "!mIsBeingDragged");

                final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
                final float x = MotionEventCompat.getX(ev, pointerIndex);
                final float xDiff = Math.abs(x - mLastMotionX);
                final float y = MotionEventCompat.getY(ev, pointerIndex);
                final float yDiff = Math.abs(y - mLastMotionY);
                if (DEBUG) Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff);
                if (xDiff > mTouchSlop && xDiff > yDiff) {
                    isVerticalMovement = false;
                    hasMovedHorizontally = true;
                    if (DEBUG) Log.v(TAG, "Starting drag!");
                    mIsBeingDragged = true;
                    requestParentDisallowInterceptTouchEvent(true);
                    mLastMotionX = x - mInitialMotionX > 0 ? mInitialMotionX + mTouchSlop :
                            mInitialMotionX - mTouchSlop;
                    mLastMotionY = y;
                    setScrollState(SCROLL_STATE_DRAGGING);
                    setScrollingCacheEnabled(true);

                    // Disallow Parent Intercept, just in case
                    ViewParent parent = getParent();
                    if (parent != null) {
                        parent.requestDisallowInterceptTouchEvent(true);
                    }
                }
                else {
                    if (yDiff > mTouchSlop) {
                        // VERTICAL SWIPE -- do stuff here...
                    }
                }
            }

}

Upvotes: 2

Kevin Murvie
Kevin Murvie

Reputation: 2652

Have you tried placing the rootView on top of the ViewPager?

That way, the ViewPager should still work although being under the rootView

Upvotes: 0

Related Questions