Set up pull to refresh for Staggered Grid View

天大地大妈咪最大 提交于 2019-12-24 08:55:40

问题


I am using Staggered Grid View-Master Library to develope the view like Pinterest and I'm quite successful in that. But now I want to implement Pull to refresh within my app. I have been using Library from johannilsson but that doesnot includes pull to refresh for staggered Grid Views. The code I have been using is this :

      ((PullToRefreshListView)getListView()).setOnRefreshListener(new OnRefreshListener() {
            @Override
            public void onRefresh() {
                // Do work to refresh the list here.
                new GetDataTask().execute();
            }
        });


      adapter = new StaggeredAdapter(AllContestsList.this, R.id.imageView1, arrContest,false,false,false);

        gridView.setAdapter(adapter);

        adapter.notifyDataSetChanged();

Help would be appreciated , Thank you.


回答1:


I faced similar issue. I found this commit in pull to refresh GIT https://github.com/chrisbanes/Android-PullToRefresh/pull/230/files. Unfortunately, I could not find it in the library. So I copied the file to my project and update it. Here is the class:

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.View;

import com.handmark.pulltorefresh.library.OverscrollHelper;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.R;
import com.origamilabs.library.views.StaggeredGridView;

public class PullToRefreshStaggeredGridView extends PullToRefreshBase<StaggeredGridView> {

private static final OnRefreshListener<StaggeredGridView> defaultOnRefreshListener = new OnRefreshListener<StaggeredGridView>() {

    @Override
    public void onRefresh(PullToRefreshBase<StaggeredGridView> refreshView) {

    }

};

public PullToRefreshStaggeredGridView(Context context) {
    super(context);

    /**
     * Added so that by default, Pull-to-Refresh refreshes the page
     */
    setOnRefreshListener(defaultOnRefreshListener);
}

public PullToRefreshStaggeredGridView(Context context, AttributeSet attrs) {
    super(context, attrs);

    /**
     * Added so that by default, Pull-to-Refresh refreshes the page
     */
    setOnRefreshListener(defaultOnRefreshListener);
}

public PullToRefreshStaggeredGridView(Context context, Mode mode) {
    super(context, mode);

    /**
     * Added so that by default, Pull-to-Refresh refreshes the page
     */
    setOnRefreshListener(defaultOnRefreshListener);
}

public PullToRefreshStaggeredGridView(Context context, Mode mode, AnimationStyle style) {
    super(context, mode, style);

    /**
     * Added so that by default, Pull-to-Refresh refreshes the page
     */
    setOnRefreshListener(defaultOnRefreshListener);
}

@Override
public final Orientation getPullToRefreshScrollDirection() {
    return Orientation.VERTICAL;
}

@Override
protected StaggeredGridView createRefreshableView(Context context, AttributeSet attrs) {
    StaggeredGridView gridView;

    if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {
        gridView = new InternalStaggeredGridViewSDK9(context, attrs);
    } else {
        gridView = new StaggeredGridView(context, attrs);
    }

    gridView.setId(R.id.gridview);
    return gridView;
}

@Override
protected boolean isReadyForPullStart() {

    boolean result = false;
    View v = getRefreshableView().getChildAt(0);
    if (getRefreshableView().getFirstPosition() == 0) {
        if (v != null) {
            // getTop() and getBottom() are relative to the ListView,
            // so if getTop() is negative, it is not fully visible
            boolean isTopFullyVisible = v.getTop() >= 0;

            result = isTopFullyVisible;
        }
    }
    return result;
}

@Override
protected boolean isReadyForPullEnd() {
    boolean result = false;
    int last = getRefreshableView().getChildCount() - 1;
    View v = getRefreshableView().getChildAt(last);

    int firstVisiblePosition = getRefreshableView().getFirstPosition();
    int visibleItemCount = getRefreshableView().getChildCount();
    int itemCount = getRefreshableView().getAdapter().getCount();
    if (firstVisiblePosition + visibleItemCount >= itemCount) {
        if (v != null) {
            boolean isLastFullyVisible = v.getBottom() <= getRefreshableView().getHeight();

            result = isLastFullyVisible;
        }
    }
    return result;
}

@Override
protected void onPtrRestoreInstanceState(Bundle savedInstanceState) {
    super.onPtrRestoreInstanceState(savedInstanceState);
}

@Override
protected void onPtrSaveInstanceState(Bundle saveState) {
    super.onPtrSaveInstanceState(saveState);
}

@TargetApi(9)
final class InternalStaggeredGridViewSDK9 extends StaggeredGridView {

    // WebView doesn't always scroll back to it's edge so we add some
    // fuzziness
    static final int OVERSCROLL_FUZZY_THRESHOLD = 2;

    // WebView seems quite reluctant to overscroll so we use the scale
    // factor to scale it's value
    static final float OVERSCROLL_SCALE_FACTOR = 1.5f;

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

    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX,
            int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {

        final boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,
                scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);

        // Does all of the hard work...
        // OverscrollHelper.overScrollBy(PullToRefreshStaggeredGridView.this,
        // deltaX, scrollX, deltaY, scrollY,
        // getScrollRange(), OVERSCROLL_FUZZY_THRESHOLD,
        // OVERSCROLL_SCALE_FACTOR, isTouchEvent);

        // Does all of the hard work...
        OverscrollHelper.overScrollBy(PullToRefreshStaggeredGridView.this, deltaX, scrollX, deltaY,
                getScrollRange(), isTouchEvent);

        return returnValue;
    }

    /**
     * Taken from the AOSP ScrollView source
     */
    private int getScrollRange() {
        int scrollRange = 0;
        if (getChildCount() > 0) {
            View child = getChildAt(0);
            scrollRange = Math.max(0, child.getHeight() - (getHeight() - getPaddingBottom() - getPaddingTop()));
        }
        return scrollRange;
    }

}
}

Use it in XML like this (replace com.example with your package):

<com.example.PullToRefreshStaggeredGridView
        xmlns:ptr="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:stretchMode="columnWidth"
        ptr:ptrMode="both"
        staggered:itemMargin="10dp"
        staggered:numColumns="3" >
</com.example.PullToRefreshStaggeredGridView>

If you want to set adapter on this gridview, do it with this code:

gridView.getRefreshableView().setAdapter(adapter);

That's all enjoy.

P.S.: If you call notifyDataSetChanged on the adapter of this gridview, it causes the view jump back to top position. You can fix it with the solution here: https://stackoverflow.com/a/5688490/1319519 .




回答2:



When I was searching for pinterest style layout on android, I found a post below.
http://www.rahuljiresal.com/2014/03/pinterest-style-layout-on-android/

Then I chose to use AndroidStaggeredGrid library as his recommend.
But it has not offered pull to refresh function.
So I decided to combine etsy's AndroidStaggeredGrid with Chris Banes' Android-PullToRefresh.

etsy's AndroidStaggeredGrid
https://github.com/etsy/AndroidStaggeredGrid

Chris Banes' Android-PullToRefresh
https://github.com/chrisbanes/Android-PullToRefresh

Here I am introducing how I did to combine those libraries.

(1) On etsy's AndroidStaggeredGrid,
StaggeredGridView has an issue for working with PullToRefresh.
I opened the issue
https://github.com/etsy/AndroidStaggeredGrid/issues/177

StaggeredGridView.java

 @Override
 protected void onSizeChanged(int w, int h) {
    super.onSizeChanged(w, h);

    // add below code in order to avoid shrinking width while being wrapped by PullToRefresh.
    if(w <= 0 || h <= 0) {
        return;
    }


(2) On Chris Banes' Android-PullToRefresh,
Create PullToRefreshStaggeredView file which code is below.

PullToRefreshStaggeredView.java

  package com.handmark.pulltorefresh.library;

  import android.annotation.TargetApi;
  import android.content.Context;
  import android.os.Build.VERSION;
  import android.os.Build.VERSION_CODES;
  import android.util.AttributeSet;
  import android.util.Log;
  import android.view.View;
  import android.view.ViewGroup;

  import com.etsy.android.grid.StaggeredGridView;
  import com.handmark.pulltorefresh.library.internal.EmptyViewMethodAccessor;

  public class PullToRefreshStaggeredView extends PullToRefreshAdapterViewBase<StaggeredGridView> {

    public PullToRefreshStaggeredView(Context context) {
        super(context);
    }

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

    public PullToRefreshStaggeredView(Context context, Mode mode) {
        super(context, mode);
    }

    public PullToRefreshStaggeredView(Context context, Mode mode, AnimationStyle style) {
        super(context, mode, style);
    }

    @Override
    public final Orientation getPullToRefreshScrollDirection() {
        return Orientation.VERTICAL;
    }

    @Override
    public void setAdapter(ListAdapter adapter) {
        ((StaggeredGridView) mRefreshableView).setAdapter(adapter);
    }

    @Override
    protected final StaggeredGridView createRefreshableView(Context context, AttributeSet attrs) {
        final StaggeredGridView gv;
        if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {
            gv = new InternalStaggeredGridViewSDK9(context, attrs);
        } else {
            gv = new InternalStaggeredGridView(context, attrs);
        }

        // Use Generated ID (from res/values/ids.xml)
        gv.setId(R.id.gridview);
        return gv;
    }

    class InternalStaggeredGridView extends StaggeredGridView implements EmptyViewMethodAccessor {

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

        @Override
        public void setEmptyView(View emptyView) {
            PullToRefreshStaggeredView.this.setEmptyView(emptyView);
        }

        @Override
        public void setEmptyViewInternal(View emptyView) {
            super.setEmptyView(emptyView);
        }
    }

    @TargetApi(9)
    final class InternalStaggeredGridViewSDK9 extends InternalStaggeredGridView {

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

        @Override
        protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX,
                int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {

            final boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,
                    scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);

            // Does all of the hard work...
            OverscrollHelper.overScrollBy(PullToRefreshStaggeredView.this, deltaX, scrollX, deltaY, scrollY, isTouchEvent);

            return returnValue;
        }
    }


  }


(3) On your application,
Test it with an activity.

PullToRefreshStaggeredListActivity.java

 public class PullToRefreshStaggeredListActivity extends Activity {

     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.pull_to_refresh_staggered_list);

         PullToRefreshStaggeredView listview = (PullToRefreshStaggeredView) findViewById(R.id.list);
         StaggeredGridView staggeredView 
            = (StaggeredGridView) ((PullToRefreshAdapterViewBase<?>) listview).getRefreshableView();

         // add header
         View header = getLayoutInflater().inflate(R.layout.header, null, false);
         staggeredView.addHeaderView(header);

         // add footer
         View footer = getLayoutInflater().inflate(R.layout.footer, null, false);
         staggeredView.addFooterView(footer);

         // set adapter
         listview.setAdapter(new MyAdapter());
     }

 }

pull_to_refresh_staggered_list.xml

  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:orientation="vertical" >

      <com.handmark.pulltorefresh.library.PullToRefreshStaggeredView
          xmlns:ptr="http://schemas.android.com/apk/res-auto"
          xmlns:app="http://schemas.android.com/apk/res-auto"
          android:id="@+id/list"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:layout_gravity="center"
          android:alwaysDrawnWithCache="true"
          android:background="#10ffff00"
          app:column_count="3"
          app:item_margin="8dp"
          ptr:ptrHeaderBackground="#10ff00ff" />

  </LinearLayout>


来源:https://stackoverflow.com/questions/18315493/set-up-pull-to-refresh-for-staggered-grid-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!