I've implemented SwipeRefreshLayout
and ViewPager
in my app but there is a big trouble: whenever I'm going to swipe left / right to switch between pages the scrolling is too sensitive. A little swipe down will trigger the SwipeRefreshLayout
refresh too.
I want to set a limit to when horizontal swipe starts, then force horizontal only until swiping is over. In other words, I want to cancel vertical swipping when finger is moving horizontally.
This problem only occurs on ViewPager
, if I swipe down and SwipeRefreshLayout
refresh function is triggered (the bar is shown) and then I move my finger horizontally, it still only allows vertical swipes.
I've tried to extend the ViewPager
class but it isn't working at all:
public class CustomViewPager extends ViewPager {
public CustomViewPager(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean in = super.onInterceptTouchEvent(ev);
if (in) {
getParent().requestDisallowInterceptTouchEvent(true);
this.requestDisallowInterceptTouchEvent(true);
}
return false;
}
}
Layout xml:
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/viewTopic"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.myapp.listloader.foundation.CustomViewPager
android:id="@+id/topicViewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
any help would be appreciated, thanks
I am not sure if you still have this issue but Google I/O app iosched solves this problem thusly:
viewPager.addOnPageChangeListener( new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled( int position, float v, int i1 ) {
}
@Override
public void onPageSelected( int position ) {
}
@Override
public void onPageScrollStateChanged( int state ) {
enableDisableSwipeRefresh( state == ViewPager.SCROLL_STATE_IDLE );
}
} );
private void enableDisableSwipeRefresh(boolean enable) {
if (swipeContainer != null) {
swipeContainer.setEnabled(enable);
}
}
I have used the same and works quite well.
EDIT: Use addOnPageChangeListener() instead of setOnPageChangeListener().
Solved very simply without extending anything
mPager.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mLayout.setEnabled(false);
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
mLayout.setEnabled(true);
break;
}
return false;
}
});
work like a charm
I've met your problem. Customize the SwipeRefreshLayout would solve the problem.
public class CustomSwipeToRefresh extends SwipeRefreshLayout {
private int mTouchSlop;
private float mPrevX;
public CustomSwipeToRefresh(Context context, AttributeSet attrs) {
super(context, attrs);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mPrevX = MotionEvent.obtain(event).getX();
break;
case MotionEvent.ACTION_MOVE:
final float eventX = event.getX();
float xDiff = Math.abs(eventX - mPrevX);
if (xDiff > mTouchSlop) {
return false;
}
}
return super.onInterceptTouchEvent(event);
}
See the ref: link
I based this off a previous answer but found this to work a bit better. The motion starts with an ACTION_MOVE event and ends in either ACTION_UP or ACTION_CANCEL in my experience.
mViewPager.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
mSwipeRefreshLayout.setEnabled(false);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mSwipeRefreshLayout.setEnabled(true);
break;
}
return false;
}
});
For some reason best known only to them, the support library developer team saw fit to forcefully intercept all vertical drag motion events from SwipeRefreshLayout
's child layout, even when a child specifically requests ownership of the event. The only thing they check for is that vertical scroll state of it's main child is at zero (in the case that it's child is vertically scrollable). The requestDisallowInterceptTouchEvent()
method has been overridden with an empty body, and the (not so) illuminating comment "Nope".
The easiest way to solve this issue would be to just copy the class from the support library into your project and remove the method override. ViewGroup
's implementation uses internal state for handling onInterceptTouchEvent()
, so you cannot simply override the method again and duplicate it. If you really want to override the support library implementation, then you will have to set up a custom flag upon calls to requestDisallowInterceptTouchEvent()
, and override onInterceptTouchEvent()
and onTouchEvent()
(or possibly hack canChildScrollUp()
) behavior based on that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With