前言:

基本上所以的移动端应用都有Listview(当然RecyclerView也一样),那必不可少的都会嵌入一个上拉加载下拉刷新的功能。这样能大大的减少用户的流量消耗,同样对于用户也有更好的用户体验。说到这个功能,那必不可少的会涉及到
SwipeRefreshLayout,这是由Google给我们封装好的一个sdk,他支持我们listview的下拉刷新功能。当然也可以自己自定义一个下拉刷新的view,这样能根据自己的项目来设计,这样更有个性化吧。不过我这仅仅使用这个SwipeRefreshLayout来构建。当然仅仅有它还是不够的,还需要对它进行一层封装,增加一个上拉加载的功能。SwipeRefreshLayout这里就不详细介绍了,网上有很多介绍资料。

先谈下SwipeRefreshLayout的封装-增加上拉加载的功能

1.我们先要有个footerview,它的作用就是当能上拉加载的时候显示的。大部分app都是一句提示,上拉加载更多
2.只有listview滑动到底部的时候才会触发上拉加载的功能,所以我们要知道listview是否滑动到底部,同样的它也决定我们footerview显示的时机。
3.通过滑动的距离来判断,我们是否在进行上拉操作。
4.通过标识来判断是否正在加载数据,避免重复上拉而导致重复调用接口。
好了,大致思路就这样,接下来就对SwipeRefreshLayout来进行封装吧,代码中都有注释,我就不细说了。
public class RefreshLayout extends SwipeRefreshLayout {//最小滑动距离,超过则判断是否是上拉操作private final int mTouchSlop;private ListView mListView;//提供获取数据接口private OnLoadListener mOnLoadListener;//用来判断是否是上拉操作private float firstTouchY;private float lastTouchY;//Listview是否正在加载数据private boolean isLoading = false;public RefreshLayout(Context context) {this(context, null);}public RefreshLayout(Context context, AttributeSet attrs) {super(context, attrs);mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();}//set the child view of RefreshLayout,ListViewpublic void setChildView(ListView mListView) {this.mListView = mListView;}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {final int action = event.getAction();switch (action) {case MotionEvent.ACTION_DOWN:firstTouchY = event.getRawY();break;case MotionEvent.ACTION_UP:lastTouchY = event.getRawY();//是否能加载数据if (canLoadMore()) {loadData();}break;default:break;}return super.dispatchTouchEvent(event);}//是否能加载数据private boolean canLoadMore() {return isBottom() && !isLoading && isPullingUp();}//判断Listview是否滑动到底部private boolean isBottom() {if (mListView.getCount() > 0) {if (mListView.getLastVisiblePosition() == mListView.getAdapter().getCount() - 1 &&mListView.getChildAt(mListView.getChildCount() - 1).getBottom() <= mListView.getHeight()) {return true;}}return false;}//是否正在上拉private boolean isPullingUp() {return (firstTouchY - lastTouchY) >= mTouchSlop;}private void loadData() {if (mOnLoadListener != null) {setLoading(true);}}public void setLoading(boolean loading) {if (mListView == null) return;isLoading = loading;if (loading) {if (isRefreshing()) {setRefreshing(false);}//避免listview刷新的时候直接滑动到顶部mListView.setSelection(mListView.getAdapter().getCount() - 1);mOnLoadListener.onLoad();} else {firstTouchY = 0;lastTouchY = 0;}}//提供接口,执行获取数据操作public void setOnLoadListener(OnLoadListener loadListener) {mOnLoadListener = loadListener;}public interface OnLoadListener {public void onLoad();}
}

footerview我就没定义在里面了,这里主要是获取footerview显示的时机。

第二部,构建一个utils,用来封装我们的刷新与加载操作,同时可以在其中添加我们的加载动画,footerview的显示时机等。

1.处理具体的上拉加载操作,下拉刷新操作,这里是通过暴露接口的方式提供给个个页面的。
2.获取数据之后的操作,往adapter中设值,以及动画,footerview的显示等。
大致上就这两个点,说的浅显点,我们无非就是要获取数据,然后把数据给显示出来。接下来看下我们utils的代码。
public class RefreshHelper <T>{//刷新框架private RefreshLayout refreshLayout;//正在加载时显示的动画,这个就要自己根据自己项目来定义了,这代码我就不贴出来了private LoadingLayout loadingLayout;//获取第几页的数据private int cuurentPage = 1;//当前页的条数private int mCurrentPageCount = 0;//是否能加载更多private boolean isLoadMore = true;//是否正在刷新, 避免接口慢的情况下,同时执行上拉下载和下拉刷新的操作private boolean isRefresh = false;//自定义的footerview,这footerview的代码就不贴了,这个自己根据自己项目的ui设计来定义吧private XListViewFooter footerView;private Context mContext;private ListView mListView;private OnGetListViewDataInterface onGetListViewDataInterface = null;public interface OnGetListViewDataInterface{//获取服务端数据接口,用于刷新以及下拉void getDataList(int currentPage);//清除adapter中的数据void clearData();//往adapter中放数据void setData();}private Handler handler;public RefreshHelper(RefreshLayout refreshLayout, LoadingLayout loadingLayout, XListViewFooter footerView, Context mContext, ListView mListView, Handler handler, OnGetListViewDataInterface onGetListViewDataInterface){this.refreshLayout = refreshLayout;this.loadingLayout = loadingLayout;this.footerView = footerView;this.mContext = mContext;this.onGetListViewDataInterface = onGetListViewDataInterface;this.mListView = mListView;this.handler = handler;init();}//初始化refreshlayout,以及加载,刷新操作private void init() {refreshLayout.setChildView(mListView);//直接转成HeaderViewListAdapter,防止强转失败异常if(mListView.getFooterViewsCount()==0){mListView.addFooterView(footerView);}//下拉刷新动画处理refreshLayout.setColorSchemeResources(R.color.color_swipeRefreshLayout1,R.color.color_swipeRefreshLayout2, R.color.color_swipeRefreshLayout3,R.color.color_swipeRefreshLayout4);//下拉刷新操作refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {@Overridepublic void onRefresh() {isRefresh = true;//避免正在下拉的时候执行上拉操作,其实已经在外层通过 isRefresh这个值来标识了,refreshLayout.setRefreshing(true);handler.postDelayed(new Runnable() {@Overridepublic void run() {loadingLayout.setLoadStrat();refreshLayout.setRefreshing(false);//每次刷新重新加载次初始数据cuurentPage = 1;onGetListViewDataInterface.clearData();onGetListViewDataInterface.getDataList(cuurentPage);}}, 2000);}});//是否加载更多refreshLayout.setOnLoadListener(new RefreshLayout.OnLoadListener() {@Overridepublic void onLoad() {//如果可以加载更多,并且不是正在获取数据,则调起接口获取数据if(isLoadMore && !isRefresh){refreshLayout.setLoading(false);footerView.loading();cuurentPage++;onGetListViewDataInterface.getDataList(cuurentPage);}else{refreshLayout.setLoading(false);}}});//设置动画效果,这个就要根据自己项目来定了,也就是一个加载动画,未加载动画定义一个点击事件,当接口获取失败时,重新调起接口loadingLayout.setBtnRetry(new View.OnClickListener() {@Overridepublic void onClick(View v) {//检查网络是否连接if (NetUtil.checkNetIsAccess(mContext)) {loadingLayout.setLoadStrat();//这里是初次进入页面调起接口失败重新调起接口时候的操作,cuurentPage = 1;onGetListViewDataInterface.getDataList(cuurentPage);} else {loadingLayout.setLoadStop(false, null, "请检查网络连接");}}});}//从服务端获取到数据之后的,后续操作public void laterHandle(List<T> mList){if(mList != null){mCurrentPageCount = mList.size();//当前页的Count>0的时候,如果当前页的Count == 20则可以上拉加载,否则不行if(mCurrentPageCount > 0){//这里Constant.PAGE_SIZE == 20if(mCurrentPageCount == Constant.PAGE_SIZE){isLoadMore = true;//这里footerview的操作是 显示提示语,上拉下载更多footerView.normal();}else{isLoadMore = false;mListView.removeFooterView(footerView);}onGetListViewDataInterface.setData();isRefresh = false;}//如果当前页码为第一页,且Record为0,则隐藏listviewif(mCurrentPageCount == 0 && cuurentPage == 1){isLoadMore = false;mListView.setVisibility(View.GONE);refreshLayout.setVisibility(View.GONE);}//如果当前页不为1,切加载到的Record为0,则已经没有更多的数据了if(mCurrentPageCount == 0 && cuurentPage>1){ToastUtil.show(mContext, "没有更多数据了");isLoadMore = false;mListView.removeFooterView(footerView);}}else {ToastUtil.show(mContext, "没有更多数据了");isLoadMore = false;mListView.setVisibility(View.GONE);refreshLayout.setVisibility(View.GONE);}//停止加载动画loadingLayout.setLoadStop(true, null, null);isRefresh = false;}public void setCuurentPage(int cuurentPage) {this.cuurentPage = cuurentPage;}public int getCuurentPage() {return cuurentPage;}public OnGetListViewDataInterface getOnGetListViewDataInterface() {return onGetListViewDataInterface;}public void setOnGetListViewDataInterface(OnGetListViewDataInterface onGetListViewDataInterface) {this.onGetListViewDataInterface = onGetListViewDataInterface;}
}

具体架构我们已经搭建好了,这里仅仅只是提供一些必要的操作,当然你也可以根据自己要处理的业务来添加内容。那接下来就是如何使用这个了。先贴下布局代码。

由于我这里也没写demo,最近一直在优化项目太忙了,就直接拿我在项目中写的框架来讲解的,所以我就只没整全部的代码来了。
然后就是我们的初始化操作,以及接口的调起还有获取数据之后的操作。
1.初始化操作代码:
2.调起接口操作:
3.获取数据之后的操作,也就是我们handlemessage中的操作
好了,整个流程已经介绍到这里了,多琢磨琢磨代码,你就会发现实现上拉加载下拉刷新其实就这么简单,希望这个框架能帮助到你。值得一提的是,我这为什么没有把这个框架写成单例模式?就是因为避免在不注意的时候可能会出现内存泄漏。所以有时候单例还是要慎用的。不过这个具体还是要根据自己实际情况来吧。

教你如何使用SwipeRefreshLayout来构建一个上拉加载下拉刷新框架相关推荐

  1. element 动态加载下拉框_记一次很坑的需求:给element-cascader添加一个重置和确定按钮...

    这帖子是不用多高超技术或者是什么歪门邪道,只是做的过程中遇到很多的坑,我感觉我做的这个没人能遇到比我还多 [因为使用场景而产生] 的坑...想记录一下,原本是产品叫我找别的级联的插件,我真的觉得不想在 ...

  2. 【FastDev4Android框架开发】RecyclerView完全解析之下拉刷新与上拉加载SwipeRefreshLayout(三十一)...

    转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/49992269 本文出自:[江清清的博客] (一).前言: [好消息] ...

  3. android SwipeRefreshLayout 增加上拉加载更多

    2019独角兽企业重金招聘Python工程师标准>>> 大家可能有的没有swipeRefreshLayout这个类,简单说一下,这是v4包里面的,19.1版本的时候就有了,但是当时的 ...

  4. 谷歌的android下拉刷新页面,Android SwipeRefreshLayout:谷歌官方SDK包中的下拉刷新

     <Android SwipeRefreshLayout:谷歌官方SDK包中的下拉刷新> 下拉刷新在如今移动开发中应用如此广泛和普遍,以至于谷歌干脆在SDK中给予支持.在android ...

  5. SwipeRefreshLayout实现上拉加载

    原来的Android SDK中并没有下拉刷新组件,但是这个组件确实绝大多数APP必备的一个部件.好在google在v4包中出了一个SwipeRefreshLayout,但是这个组件只支持下拉刷新,不支 ...

  6. 手把手教你实现Android RecyclerView上拉加载功能

    心灵鸡汤:知之者不如好之者,好之者不如乐之者. 摘要 一直在用到RecyclerView时都会微微一颤,因为一直都没去了解怎么实现上拉加载,受够了每次去Github找开源引入,因为感觉就为了一个上拉加 ...

  7. 使用SwipeRefreshLayout和RecyclerView实现仿“简书”下拉刷新和上拉加载更多

    原文地址: http://blog.csdn.net/leoleohan/article/details/50989549/ 一.概述 我们公司目前开发的所有Android APP都是遵循iOS风格设 ...

  8. 结合SwipeRefreshLayout可以上拉加载更多下拉刷新的RecyclerView

    源码下载地址:http://download.csdn.net/detail/zhou_anzhuojinjie/9661542 话不多说直接上代码 dependencies {compile fil ...

  9. android vlayout 刷新,使用vlayout轻松构建复杂布局页面上拉加载

    设计 拿到了新项目的设计图,如图所示: 乐烹APP-首页.png 构建这个页面,如果没有滑动到底部加载更多功能,可以考虑用scollerview中一点点画布局.如果需要加载 更多的话,就必须要考虑列表 ...

最新文章

  1. 记住,永远不要在MySQL中使用“utf8”
  2. 产品设计技术公开-一种扼杀对手的方式
  3. ImportError: /opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so: undefined symbol: PyCObject_Type
  4. PHP各个组件或工具的安装与使用
  5. Linux与Windows比较出的20个优势
  6. Android7.0 Doze模式分析(一)Doze介绍 amp; DeviceIdleController
  7. React版本更新及升级须知(持续更新)
  8. html js css如何关联_会html+css+js就能把前端项目发布到多个平台
  9. Transformer组件很重要Attention is all you need
  10. scala编程第16章学习笔记(3)——List类的高阶方法
  11. Kendo UI 模板概述
  12. osgb转3dtiles 原理_自动控制原理实验箱无法通行故障维修
  13. 令牌环桶算法的使用案例
  14. 【天光学术】休闲体育论文:中小学学生羽毛球运动员心理训练方法研究
  15. 基于HyperLPR的车牌识别(十三)
  16. 什么软件可以把qlv格式转换成mp4
  17. bugku——宽带信息泄露(RouterPassView 查看路由器配置信息)
  18. 计算机水利工程制图教程,《水利工程制图》.pdf
  19. 用python绘制叠加等边三角形_使用turtle库绘制叠加等边三角形
  20. 3.13 speculative generality (夸夸其谈未来性)

热门文章

  1. 分享143个ASP源码,总有一款适合您
  2. 颜宁发微博“求救” 要投拆造谣公众号
  3. OCR(脱机手写汉字识别与印刷汉字识别)
  4. REW声学测试(六):信号与测量
  5. ACdream 1224 Robbers
  6. 拼多多2018校招—Anniversary
  7. BKEX Global研究院最新市场信息解读
  8. python 三个点‘...’、Ellipsis符号
  9. 自动弹图片html,HTML图片预览弹出层实现
  10. java公路车组装教程_自行车DIY入门教程,图文展示自行车组装全过程。(原创图文,转载请注明出处)...