SwipeRefreshLayout with vertical view pager to only refresh on the topmost fragment

2.8k views Asked by At

I've tried to implement swiperefreshlayout in my code but it keeps refreshing the entire pager instead of just refreshing when i'm on the first Fragment i.e the 0th Fragment. I tried setting refresh to false as shown, but the loader still appears, and doesn't reset when I go back to the 0th Fragment again. On setting swiperefreshlayout.enable(false), I can't refresh it anywhere. Can anyone suggest an alternative? This is my XML file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/parentLinearLayout"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipe_refresh_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <ScrollView
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:fillViewport="true">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">
            <lbbdapp.littleblackbook.com.littleblackbook.Support.VerticalViewPager
                android:id="@+id/verticalViewPager"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content" />
            </LinearLayout>
        </ScrollView>
    </android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>

And this is my activity:

public class FeedActivity extends ActionBarActivity {

PageAdapter mPageAdapter;
ProgressBar mProgressBar;
ProgressDialog prog;
ViewPager pager;
String article_id;
private float x1, x2;
SwipeRefreshLayout mSwipeRefreshLayout;

ArrayList<FragmentObject> mObjectsDataList;
ArrayList<ArticleObject> mArticleDataList=new ArrayList<ArticleObject>();


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setContentView(R.layout.feed_layout);
    mObjectsDataList = new ArrayList<FragmentObject>();

    DataFetcherTask myTask = new DataFetcherTask();
    myTask.execute();

    mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
    mSwipeRefreshLayout.setColorScheme(android.R.color.holo_blue_bright,
            android.R.color.holo_blue_dark,
            android.R.color.holo_purple,
            android.R.color.darker_gray);
    pager=(ViewPager)findViewById(R.id.verticalViewPager);



    mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {

            if(pager.getCurrentItem()==0) {
                Log.wtf("current item is 0", "0");
                mSwipeRefreshLayout.setRefreshing(true);
                Log.wtf("Swiping", "Refreshing");
                (new Handler()).postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mSwipeRefreshLayout.setRefreshing(false);
                        DataFetcherTask myTask = new DataFetcherTask();
                        myTask.execute();
                    }
                }, 3000);

            }
            else{
                mSwipeRefreshLayout.setRefreshing(false);

            }
        }

    });


}

This is my vertical ViewPager:

public class VerticalViewPager extends ViewPager {

public VerticalViewPager(Context context) {
    super(context);
    init();
}

public VerticalViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

private void init() {
    // The majority of the magic happens here
    setPageTransformer(true, new VerticalPageTransformer());
    // The easiest way to get rid of the overscroll drawing that happens on the left and right
    setOverScrollMode(OVER_SCROLL_NEVER);
}

private class VerticalPageTransformer implements ViewPager.PageTransformer {

    @Override
    public void transformPage(View view, float position) {

        if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(0);

        } else if (position <= 1) { // [-1,1]
            view.setAlpha(1);

            // Counteract the default slide transition
            view.setTranslationX(view.getWidth() * -position);

            //set Y position to swipe in from top
            float yPosition = position * view.getHeight();
            view.setTranslationY(yPosition);

        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            view.setAlpha(0);
        }
    }
}

/**
 * Swaps the X and Y coordinates of your touch event.
 */
private MotionEvent swapXY(MotionEvent ev) {
    float width = getWidth();
    float height = getHeight();

    float newX = (ev.getY() / height) * width;
    float newY = (ev.getX() / width) * height;

    ev.setLocation(newX, newY);

    return ev;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev){
    boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
    swapXY(ev); // return touch coordinates to original reference frame for any child views
    return intercepted;
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    return super.onTouchEvent(swapXY(ev));
  }

 }
2

There are 2 answers

3
strike On

Instead of extending SwipeRefesh over ViewGroup use it inside the each Fragment of ViewPager. Once this is resolved now you need to check scroll down gesture of ViewPager and SwipeRefresh.

public class NEWSwipeRefresh extends SwipeRefreshLayout {

    private View mTargetView;

    public NEWSwipeRefresh(Context context) {
        this(context, null);
    }

    public NEWSwipeRefresh(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setTarget(View view) {
        mTargetView = view;
    }

    @Override
    public boolean canChildScrollUp() {
        if (mTargetView instanceof YOURVIEW) {
            final StaggeredGridView absListView = (YOURVIEW)mTargetView;
            return absListView.getChildCount() > 0
                    && (absListView.getFirstVisiblePosition() > 0 || absListView
                            .getChildAt(0).getTop() < absListView
                            .getPaddingTop());
        } else {
            return super.canChildScrollUp();
        }
    }

}

Normally swipe refresh returns -1 and it gives swipe gesture to it's parent now I have overridden it here for listview/gridview so that it can check for visible items, if it is on top then it will give swipe to parent or otherwise it will give it to children.

0
Leap Hawk On

Well, I was trying to figure this out since few days and it's quite simple. Just put the SwipeRefreshLayout as the parent element of ViewPager and just disable the SwipeRefreshLayout on the particular fragment using OnPageChangeListener as follows:

//  viewpager change listener
 OnPageChangeListener viewPagerPageChangeListener = new OnPageChangeListener() {

  @Override
  public void onPageSelected(int position) {

     //for the 0th pos disable SwipeRefreshLayout;
     if(position != 0){
        swipeRefreshLayout.setEnabled(false);
     }else swipeRefreshLayout.setEnabled(true);

  }

  @Override
  public void onPageScrolled(int arg0, float arg1, int arg2) {

  }

  @Override
  public void onPageScrollStateChanged(int arg0) {

  }};