瀑布流在刚出来的时候很火,大家都觉得下过很炫,于是乎我也玩了一把,但结果,应用到具体场景的时候,我们需要使用上拉刷新功能,开源的效果不能达到,于是乎,经过大神指点,重新实现了这一效果。
首先,我们需要引用瀑布流的工程,github项目地址: https://github.com/paulzeng/AndroidStaggeredGrid,这个项目我已经fork到了我的主页,下载,然后对其library进行引用。
然后我们引入下拉刷新的工程,github项目地址: https://github.com/paulzeng/Android-PullToRefresh,这个项目我也fork了,下载,引入library。我们需要修改PullToRefreshBase.java类,加入两个方法,用于判断是上拉还是下拉。
public boolean isHeaderShown() {
return getHeaderLayout().isShown();
}
public boolean isFooterShown() {
return getFooterLayout().isShown();
}
至此,工程库的引用,我们已经完成,接下来,我们需要自定义
PullToRefreshStaggeredGridView
类,将瀑布流与刷新组件合并。
import android.annotation.SuppressLint;
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.etsy.android.grid.StaggeredGridView;
import com.handmark.pulltorefresh.library.OverscrollHelper;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.R;
@SuppressLint("NewApi")
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().getFirstVisiblePosition() == 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()
.getFirstVisiblePosition();
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, 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;
}
}
}
然后我们自定义布局文件,使用我们重新写好的控件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFF"
android:orientation="vertical" >
<com.thomas.pulltorefreshstaggeredgridview.PullToRefreshStaggeredGridView
android:id="@+id/pull_grid_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="#F0F0F0"
android:cacheColorHint="#00000000"
android:fadingEdge="none"
android:overScrollMode="never"
android:scrollbars="none"
app:column_count="2"
app:item_margin="8dp" />
</LinearLayout>
然后我们在activity中进行coding
import java.util.ArrayList;
import java.util.List;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import com.etsy.android.grid.StaggeredGridView;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;
import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
@SuppressLint("NewApi")
public class MainActivity extends Activity implements
OnRefreshListener<StaggeredGridView> {
private List<PhotoBean> photos;
private StaggeredGridView mDongTaiGridView;
private MyPhotoAdapter mAdapter;
/** 下来刷新 **/
private PullToRefreshStaggeredGridView mPullToRefreshStaggerdGridView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initImageLoader(this);
setContentView(R.layout.activity_main);
photos = getPhotos();
mAdapter = new MyPhotoAdapter(this, photos);
mPullToRefreshStaggerdGridView = (PullToRefreshStaggeredGridView) this
.findViewById(R.id.pull_grid_view);
mPullToRefreshStaggerdGridView.setMode(Mode.PULL_FROM_START);
mPullToRefreshStaggerdGridView.setMode(Mode.BOTH);
mPullToRefreshStaggerdGridView.setOnRefreshListener(this);
mDongTaiGridView = mPullToRefreshStaggerdGridView.getRefreshableView();
mDongTaiGridView.setAdapter(mAdapter);
}
private List<PhotoBean> getPhotos() {
List<PhotoBean> photos = new ArrayList<PhotoBean>();
PhotoBean PhotoBean = new PhotoBean(
"http://img4q.duitang.com/uploads/item/201506/29/20150629140736_5JR8c.jpeg",
"夏天的风");
photos.add(PhotoBean);
PhotoBean = new PhotoBean(
"http://img5q.duitang.com/uploads/item/201506/29/20150629141607_LNFkx.thumb.700_0.jpeg",
"夏天的风");
photos.add(PhotoBean);
PhotoBean = new PhotoBean(
"http://img5q.duitang.com/uploads/item/201506/29/20150629141550_MuVm5.jpeg",
"夏天的风");
photos.add(PhotoBean);
PhotoBean = new PhotoBean(
"http://img5q.duitang.com/uploads/item/201506/29/20150629141740_TUB2H.jpeg",
"夏天的风");
photos.add(PhotoBean);
PhotoBean = new PhotoBean(
"http://img4q.duitang.com/uploads/item/201506/29/20150629141716_nCUrG.jpeg",
"夏天的风");
photos.add(PhotoBean);
PhotoBean = new PhotoBean(
"http://cdnq.duitang.com/uploads/item/201506/29/20150629141656_5GBzS.jpeg",
"夏天的风");
photos.add(PhotoBean);
PhotoBean = new PhotoBean(
"http://img4q.duitang.com/uploads/item/201506/29/20150629141634_CEida.jpeg",
"夏天的风");
photos.add(PhotoBean);
PhotoBean = new PhotoBean(
"http://img5q.duitang.com/uploads/item/201506/29/20150629141236_sAHim.jpeg",
"夏天的风");
photos.add(PhotoBean);
PhotoBean = new PhotoBean(
"http://img4q.duitang.com/uploads/item/201506/29/20150629141218_ezRd4.jpeg",
"夏天的风");
photos.add(PhotoBean);
PhotoBean = new PhotoBean(
"http://cdnq.duitang.com/uploads/item/201506/29/20150629141200_nykzY.jpeg",
"夏天的风");
photos.add(PhotoBean);
PhotoBean = new PhotoBean(
"http://img4q.duitang.com/uploads/item/201506/29/20150629141125_FCtVN.jpeg",
"夏天的风");
photos.add(PhotoBean);
PhotoBean = new PhotoBean(
"http://img4q.duitang.com/uploads/item/201506/29/20150629141108_mBrUc.jpeg",
"夏天的风");
photos.add(PhotoBean);
PhotoBean = new PhotoBean(
"http://cdnq.duitang.com/uploads/item/201506/29/20150629141052_cdFuA.thumb.700_0.jpeg",
"夏天的风");
photos.add(PhotoBean);
PhotoBean = new PhotoBean(
"http://cdnq.duitang.com/uploads/item/201506/29/20150629141030_zv2Rt.jpeg",
"夏天的风");
photos.add(PhotoBean);
PhotoBean = new PhotoBean(
"http://img5q.duitang.com/uploads/item/201506/29/20150629140948_UMWTQ.jpeg",
"夏天的风");
photos.add(PhotoBean);
return photos;
}
@Override
public void onRefresh(PullToRefreshBase<StaggeredGridView> refreshView) {
// TODO Auto-generated method stub
if (refreshView.isHeaderShown()) {
} else {
}
}
public void initImageLoader(Context context) {
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
context).threadPriority(Thread.NORM_PRIORITY - 2)
.denyCacheImageMultipleSizesInMemory()
.discCacheFileNameGenerator(new Md5FileNameGenerator())
.tasksProcessingOrder(QueueProcessingType.LIFO)
.writeDebugLogs() // Remove for release app
.build();
ImageLoader.getInstance().init(config);
}
}
接下来,请看效果图:
如果还有不清楚的,可以进入我的github主页,下载完整代码 demo
点击打开链接
项目我会进一步在github上面进行完整,还希望能与大家一起完善。