Set Up Pull To Refresh For Staggered Grid View
Solution 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;
publicclassPullToRefreshStaggeredGridViewextendsPullToRefreshBase<StaggeredGridView> {
privatestaticfinal OnRefreshListener<StaggeredGridView> defaultOnRefreshListener = newOnRefreshListener<StaggeredGridView>() {
@OverridepublicvoidonRefresh(PullToRefreshBase<StaggeredGridView> refreshView) {
}
};
publicPullToRefreshStaggeredGridView(Context context) {
super(context);
/**
* Added so that by default, Pull-to-Refresh refreshes the page
*/
setOnRefreshListener(defaultOnRefreshListener);
}
publicPullToRefreshStaggeredGridView(Context context, AttributeSet attrs) {
super(context, attrs);
/**
* Added so that by default, Pull-to-Refresh refreshes the page
*/
setOnRefreshListener(defaultOnRefreshListener);
}
publicPullToRefreshStaggeredGridView(Context context, Mode mode) {
super(context, mode);
/**
* Added so that by default, Pull-to-Refresh refreshes the page
*/
setOnRefreshListener(defaultOnRefreshListener);
}
publicPullToRefreshStaggeredGridView(Context context, Mode mode, AnimationStyle style) {
super(context, mode, style);
/**
* Added so that by default, Pull-to-Refresh refreshes the page
*/
setOnRefreshListener(defaultOnRefreshListener);
}
@Overridepublicfinal Orientation getPullToRefreshScrollDirection() {
return Orientation.VERTICAL;
}
@Overrideprotected StaggeredGridView createRefreshableView(Context context, AttributeSet attrs) {
StaggeredGridView gridView;
if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {
gridView = newInternalStaggeredGridViewSDK9(context, attrs);
} else {
gridView = newStaggeredGridView(context, attrs);
}
gridView.setId(R.id.gridview);
return gridView;
}
@OverrideprotectedbooleanisReadyForPullStart() {
booleanresult=false;
Viewv= 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 visiblebooleanisTopFullyVisible= v.getTop() >= 0;
result = isTopFullyVisible;
}
}
return result;
}
@OverrideprotectedbooleanisReadyForPullEnd() {
booleanresult=false;
intlast= getRefreshableView().getChildCount() - 1;
Viewv= getRefreshableView().getChildAt(last);
intfirstVisiblePosition= getRefreshableView().getFirstPosition();
intvisibleItemCount= getRefreshableView().getChildCount();
intitemCount= getRefreshableView().getAdapter().getCount();
if (firstVisiblePosition + visibleItemCount >= itemCount) {
if (v != null) {
booleanisLastFullyVisible= v.getBottom() <= getRefreshableView().getHeight();
result = isLastFullyVisible;
}
}
return result;
}
@OverrideprotectedvoidonPtrRestoreInstanceState(Bundle savedInstanceState) {
super.onPtrRestoreInstanceState(savedInstanceState);
}
@OverrideprotectedvoidonPtrSaveInstanceState(Bundle saveState) {
super.onPtrSaveInstanceState(saveState);
}
@TargetApi(9)finalclassInternalStaggeredGridViewSDK9extendsStaggeredGridView {
// WebView doesn't always scroll back to it's edge so we add some// fuzzinessstaticfinalintOVERSCROLL_FUZZY_THRESHOLD=2;
// WebView seems quite reluctant to overscroll so we use the scale// factor to scale it's valuestaticfinalfloatOVERSCROLL_SCALE_FACTOR=1.5f;
publicInternalStaggeredGridViewSDK9(Context context, AttributeSet attrs) {
super(context, attrs);
}
@OverrideprotectedbooleanoverScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX,
int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
finalbooleanreturnValue=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
*/privateintgetScrollRange() {
intscrollRange=0;
if (getChildCount() > 0) {
Viewchild= 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.PullToRefreshStaggeredGridViewxmlns: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 .
Solution 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
@OverrideprotectedvoidonSizeChanged(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;
publicclassPullToRefreshStaggeredViewextendsPullToRefreshAdapterViewBase<StaggeredGridView> {
publicPullToRefreshStaggeredView(Context context) {
super(context);
}
publicPullToRefreshStaggeredView(Context context, AttributeSet attrs) {
super(context, attrs);
}
publicPullToRefreshStaggeredView(Context context, Mode mode) {
super(context, mode);
}
publicPullToRefreshStaggeredView(Context context, Mode mode, AnimationStyle style) {
super(context, mode, style);
}
@Overridepublicfinal Orientation getPullToRefreshScrollDirection() {
return Orientation.VERTICAL;
}
@OverridepublicvoidsetAdapter(ListAdapter adapter) {
((StaggeredGridView) mRefreshableView).setAdapter(adapter);
}
@Overrideprotectedfinal StaggeredGridView createRefreshableView(Context context, AttributeSet attrs) {
final StaggeredGridView gv;
if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {
gv = newInternalStaggeredGridViewSDK9(context, attrs);
} else {
gv = newInternalStaggeredGridView(context, attrs);
}
// Use Generated ID (from res/values/ids.xml)
gv.setId(R.id.gridview);
return gv;
}
classInternalStaggeredGridViewextendsStaggeredGridViewimplementsEmptyViewMethodAccessor {
publicInternalStaggeredGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@OverridepublicvoidsetEmptyView(View emptyView) {
PullToRefreshStaggeredView.this.setEmptyView(emptyView);
}
@OverridepublicvoidsetEmptyViewInternal(View emptyView) {
super.setEmptyView(emptyView);
}
}
@TargetApi(9)finalclassInternalStaggeredGridViewSDK9extendsInternalStaggeredGridView {
publicInternalStaggeredGridViewSDK9(Context context, AttributeSet attrs) {
super(context, attrs);
}
@OverrideprotectedbooleanoverScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX,
int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
finalbooleanreturnValue=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
publicclassPullToRefreshStaggeredListActivityextendsActivity {
@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pull_to_refresh_staggered_list);
PullToRefreshStaggeredViewlistview= (PullToRefreshStaggeredView) findViewById(R.id.list);
StaggeredGridViewstaggeredView= (StaggeredGridView) ((PullToRefreshAdapterViewBase<?>) listview).getRefreshableView();
// add headerViewheader= getLayoutInflater().inflate(R.layout.header, null, false);
staggeredView.addHeaderView(header);
// add footerViewfooter= getLayoutInflater().inflate(R.layout.footer, null, false);
staggeredView.addFooterView(footer);
// set adapter
listview.setAdapter(newMyAdapter());
}
}
pull_to_refresh_staggered_list.xml
<LinearLayoutxmlns: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.PullToRefreshStaggeredViewxmlns: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>
Post a Comment for "Set Up Pull To Refresh For Staggered Grid View"