能够下拉刷新和上拉加载的瀑布流

瀑布流在刚出来的时候很火,大家都觉得下过很炫,于是乎我也玩了一把,但结果,应用到具体场景的时候,我们需要使用上拉刷新功能,开源的效果不能达到,于是乎,经过大神指点,重新实现了这一效果。

首先,我们需要引用瀑布流的工程,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上面进行完整,还希望能与大家一起完善。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-03 07:24:31

能够下拉刷新和上拉加载的瀑布流的相关文章

支持下拉刷新和上划加载更多的自定义RecyclerView(仿XListView效果)

首先看效果 下拉刷新:        上划加载        在项目更新的过程中,遇到了一个将XListView换成recyclerView的需求,而且更换完之后大体效果不能变,但是对于下拉刷新这样的效果,谷歌给出的解决方案是把RecyclerView放在一个SwipeRefreshLayout中,但是这样其实是拉下一个小圆形控件实现的,和XListView的header效果不同.在网上找了很多的别人代码,都没有实现我想要的效果,于是自己动手写了一个. 具体实现的效果有以下几条 下拉刷新功能:

最新Android ListView 下拉刷新 上滑加载

开发项目过程中基本都会用到listView的下拉刷新和上滑加载更多,之前大家最常用的应该是pull to refresh或它的变种版吧,google官方在最新的android.support.v4包中增加了一个新类SwipeRefreshLayout,地址 这个类的作用就是提供官方的下拉刷新,并且效果相当不错,而上拉加载更多则用我们自定义的listview,也是相当简单. 下拉刷新 简单的介绍下: 首先它是一个viewgroup,但是它只允许有一个子控件,子控件能是任何view,使用的时候,所在

使用PullToRefresh实现下拉刷新和上拉加载

使用PullToRefresh实现下拉刷新和上拉加载 分类: Android2013-12-20 15:51 78158人阅读 评论(91) 收藏 举报 Android下拉刷新上拉加载PullToRefresh PullToRefresh是一套实现非常好的下拉刷新库,它支持: 1.ListView 2.ExpandableListView 3.GridView 4.WebView 等多种常用的需要刷新的View类型,而且使用起来也十分方便. (下载地址:https://github.com/ch

IOS 开发下拉刷新和上拉加载更多

IOS 开发下拉刷新和上拉加载更多 简介 1.常用的下拉刷新的实现方式 (1)UIRefreshControl (2)EGOTTableViewrefresh (3)AH3DPullRefresh (4)MJRefresh (5)自己实现 2.AH3DPullRefresh实现下拉刷新和上拉下载的步骤 添加UIScrollView+AH3DPullRefresh.h 和UIScrollView+AH3DPullRefresh.m两个文件,由此可知,它是基于UIScrollView的方法. 在bu

iOS学习之路--下拉刷新和上拉加载更多

iOS学习之路--下拉刷新和上拉加载更多 简介 本文中笔者将和大家分享应用app中常用到的表单内容的下拉刷新和上拉加载更多的功能实现的方法. 内容 1.有哪些实现方法与各方法的优劣 使用过美团,大众点评的朋友们应该有注意到,当你向上滑动表单的时候会有更多的店铺加载进你的表单中,而当你下滑表单顶的时候,则会刷新表单的内容并从网络上获取最新的信息.通过下拉刷新和上拉加载更多的功能,使app可以获取更多用户想要的信息和获取最新的信息.那么这种功能如何实现呢,还请跟着笔者继续往下看. 目前来说,主要的实

Android 使用PullToRefresh实现下拉刷新和上拉加载(ExpandableListView)

PullToRefresh是一套实现非常好的下拉刷新库,它支持: 1.ListView 2.ExpandableListView 3.GridView 4.WebView 等多种常用的需要刷新的View类型,而且使用起来也十分方便. (下载地址:https://github.com/chrisbanes/Android-PullToRefresh) 下载完成,将它导入到eclipse中,作为一个library导入到你的工程中就好了. 一.废话少说,下拉刷新Go. 1.在你的布局文件中加上你想用的

【好程序员笔记分享】——下拉刷新和上拉加载更多

-iOS培训,iOS学习-------型技术博客.期待与您交流!------------ iOS学习之路--下拉刷新和上拉加载更多 简介 本文中笔者将和大家分享应用app中常用到的表单内容的下拉刷新和上拉加载更多的功能实现的方法. 内容 1.有哪些实现方法与各方法的优劣 使用过美团,大众点评的朋友们应该有注意到,当你向上滑动表单的时候会有更多的店铺加载进你的表单中,而当你下滑表单顶的时候,则会刷新表单的内容 并从网络上获取最新的信息.通过下拉刷新和上拉加载更多的功能,使app可以获取更多用户想要

下拉刷新和上拉加载的原理

很多App中,新闻或者展示类都存在下拉刷新和上拉加载的效果,网上提供了实现这种效果的第三方类(详情请见MJRefresh和EGOTableViewPullRefresh),用起来很方便,但是闲暇之余,我们可以思考下,这种效果实现的原理是什么,我以前说过,只要是动画都是骗人的,只要不是硬件问题大部分效果都能在系统UI的基础上做出来. @下面是关键代码分析: // 下拉刷新的原理 - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scro

不借助第三方插件利用ScrollView自身delegate实现下拉刷新和上拉加载

下拉刷新功能基本上在所有的app中都会被用到,而且这个功能已经被apple集成进去了,不过必须得是在tableViewController中才有,是一个叫做UIRefreshControl的控件,想看效果可以看手机QQ上面联系人列表下拉后的刷新.这里不多介绍. 本篇blog主要介绍如何在scrollview中实现下拉刷新的效果.因为有些时候我们可能更多地希望直接在scrollview中展现,而不是一定要局限于tableviewcontroller. 当然网上有很多下拉刷新和上拉加载的第三方控件,

Android 5.X新特性之为RecyclerView添加下拉刷新和上拉加载及SwipeRefreshLayout实现原理

RecyclerView已经写过两篇文章了,分别是Android 5.X新特性之RecyclerView基本解析及无限复用 和 Android 5.X新特性之为RecyclerView添加HeaderView和FooterView,既然来到这里还没学习的,先去学习下吧. 今天我们的主题是学习为RecyclerView添加下拉刷新和上拉加载功能. 首先,我们先来学习下拉刷新,google公司已经为我们提供的一个很好的包装类,那就是SwipeRefreshLayout,这个类可以支持我们向下滑动并进