Reputation: 365
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
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
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