17

I have a ViewPager wrapped inside a SwipeRefreshLayout. Sometimes, when I swipe to the left/right the SRL get's triggered. This mostly happens when I'm at the top of my fragment.

How do I solve this? Do I need to listen to some kind of event in order to disable the SRL during a certain time? I haven't really found anything about it so I doubt this is an actual bug by Google but rather am I implementing something incorrectly? Any ideas on this?

That's my layout:

<android.support.v4.widget.SwipeRefreshLayout
    android:id="@+id/mainSwipeContainer"
    android:layout_width="wrap_content"
    android:layout_height="match_parent">

    <android.support.v4.view.ViewPager
        android:id="@+id/mainViewPager"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</android.support.v4.widget.SwipeRefreshLayout>

Thanks! Let me know if I'm missing out any information.

Crosswind
  • 940
  • 1
  • 10
  • 26
  • use SwipeRefreshLayout inside of fragment which is set inside ViewPager – Dhaval Parmar Mar 03 '16 at 10:14
  • @DhawalSodhaParmar I used to have that but since every refresh always refreshes the whole ViewPager I thought putting it outside of that would make more sense! For example - if I refresh on one tab and then scroll the right the app is still refreshing but the indicator won't be shown on the new tab. – Crosswind Mar 03 '16 at 19:33

4 Answers4

35

I managed to solve it:

mainViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mainTabLayout) {
    @Override
    public void onPageScrollStateChanged(int state) {
        toggleRefreshing(state == ViewPager.SCROLL_STATE_IDLE);
    }
});

your toggleRefreshing() should then look something like this:

public void toggleRefreshing(boolean enabled) {
    if (swipeRefreshLayout != null) {
        swipeRefreshLayout.setEnabled(enabled);
    }
}
Amit Yadav
  • 32,664
  • 6
  • 42
  • 57
Crosswind
  • 940
  • 1
  • 10
  • 26
7

Checking the page scroll state is a good approach but when a user changed the page then the animating spinner will disappear and it's bad UX.

To fix this:

viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout) {
    @Override
    public void onPageScrollStateChanged(int state) {
        if (swipeRefreshLayout != null && !swipeRefreshLayout.isRefreshing()) {
            swipeRefreshLayout.setEnabled(state == ViewPager.SCROLL_STATE_IDLE);
        }
    }
});
Gombal
  • 131
  • 1
  • 8
  • Combination of Crosswind solution and alexwan02 solution worked like charm. Thank you very much guys. I got stuck with this. – Sharad Oct 03 '18 at 04:46
3
public class CSwipeRefreshLayout extends SwipeRefreshLayout {
  private int mTouchSlop;
  private float mPrevx;
  private float mPrevy;
  public CSwipeRefreshLayout(Context context) {
    this(context, null);
  }

  public CSwipeRefreshLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
  }

  @Override
  public boolean onInterceptTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
      case MotionEvent.ACTION_DOWN:
        mPrevx = MotionEvent.obtain(ev).getX();
        mPrevy = MotionEvent.obtain(ev).getY();
        break;
      case MotionEvent.ACTION_MOVE:
        final float evX = ev.getX();
        final float evy = ev.getY();
        float xDiff = Math.abs(evX - mPrevx);
        float yDiff = Math.abs(evy - mPrevy);
        if (xDiff > mTouchSlop && xDiff > yDiff) {
          return false;
        }
    }
    return super.onInterceptTouchEvent(ev);
  }
}
alexwan02
  • 723
  • 6
  • 10
3

inspired by @Crosswind and @Gombal: kotlin extension function solution for ViewPager2

binding.topViewPager.ignorePullToRefresh(binding.swipeRefreshLayout)

fun ViewPager2.ignorePullToRefresh(swipeRefreshLayout: SwipeRefreshLayout) {
    this.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
        override fun onPageScrollStateChanged(state: Int) {
            super.onPageScrollStateChanged(state)
            if (!swipeRefreshLayout.isRefreshing) {
                swipeRefreshLayout.isEnabled = state == SCROLL_STATE_IDLE
            }
        }
    })
}
Weiyi
  • 1,843
  • 2
  • 22
  • 34