Reputation: 21
I have an activity holding a viewpager. One of the fragments in the viewpager includes a listview that covers almost the entire screen but only passively has to display items (no click on items required).
I've tried several options found on SO to disable clicks on the listview and/or it's adapter or building listener that do not consume the listview/adapter's clicks, etc. but none solved my issue:
When the listview is full of items I have to swipe at the very outer border of the display to move to another fragment of the viewpager. On the other fragments for example I dont have listviews but other views like maps and can swipe between the fragments when doing the swipe gesture directly on the middle of the display.
For a consistent user experience I also want this behaviour on the fragment holding the passive listview.
Thank you.
Upvotes: 1
Views: 566
Reputation:
Create a custom ViewPager by extending it and implement dispatchTouchEvent.
We start tracking the touch ( with the pixel positions on sceen ) in ACTION_DOWN
. When we see that it's a horizontal swipe, we do not call super.dispatchTouchEvent( event )
- which would do the default onTouch routing and make certain child views consume the horizontal swipe too - but call onTouchEvent( event )
instead in ACTION_MOVE
and also in ACTION_UP
.
public class MyViewPager extends ViewPager {
private float mLastX;
private float mLastY;
private final int mTouchSlop = ViewConfiguration.get( getContext() ).getScaledTouchSlop();
private float mStartX;
public MyViewPager( Context context ) {
super( context );
}
public MyViewPager( Context context, AttributeSet attrs ) {
super( context, attrs );
}
@Override
public boolean dispatchTouchEvent( MotionEvent event ) {
switch( event.getAction() ) {
case MotionEvent.ACTION_DOWN:
mLastX = event.getX();
mLastY = event.getY();
mStartX = event.getX();
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
onTouchEvent( event );
break;
case MotionEvent.ACTION_MOVE:
float x = event.getX();
float y = event.getY();
float xDelta = x - mLastX;
float xDeltaAbs = Math.abs( xDelta );
float yDeltaAbs = Math.abs( y - mLastY );
float xDeltaTotal = x - mStartX;
if( Math.abs( xDeltaTotal ) > mTouchSlop )
if( xDeltaAbs > yDeltaAbs )
return onTouchEvent( event );
}
return super.dispatchTouchEvent( event );
}
}
Upvotes: 1
Reputation: 2161
public boolean onTouch(View v, MotionEvent e) {
if(e.getAction() == MotionEvent.ACTION_DOWN){
listItem.getParent().requestDisallowInterceptTouchEvent(true);
}
}
Upvotes: 0