一个简单好用的下拉刷新、上拉加载控件

*本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布

本文为原创,转载必须保留出处!
http://www.jianshu.com/p/1a82cdab2249

有更新:

  • 最新的库版本为1.0.2(兼容旧版本,旧版本是1.0.0),完整的库地址:
    compile'com.zt.maven.widget:refreshview:1.0.2'
  • 更新说明:
    1 - 反注册DataObserver时添加判断,避免使用时多次调用产生bug
    2 - 私有化com.android.support:appcompat-v7,避免使用时版本冲突

写在前面:

  • 一个支持网络错误重试、无数据页(可自定义)、无网络界面(可自定义)的上拉加载更多,下拉刷新控件。

  • 话不多说(无图说个✖️)


    效果(由于模拟器有点卡顿,但所有效果都展示出来了).gif
  • 为了满足大家活多事急找来即用的心态,我先上干货,怎么用?

基本用法(分为1,2,3步)

ps:如果项目需要更加完善的ui显示,如:进入后界面自动刷新、网络错误重试、无数据页(可自定义)、无网络界面(可自定义)的功能请接着前三步往下看、往下看

  1. 项目中添加依赖
    最新版本(兼容旧版本): compile 'com.zt.maven.widget:refreshview:1.0.2'
    旧版本:compile 'com.zt.maven.widget:refreshview:1.0.0'
  1. 初始化控件
    可动态代码引入,也可静态xml添加,依个人喜好和实际情况
  2. 调用
 refreshView.setOnLoadListener(new CustomRefreshView.OnLoadListener() {
            @Override
            public void onRefresh() {
                
                //下拉刷新,添加你刷新后的逻辑
                
                //加载完成时,隐藏控件下拉刷新的状态
                refreshView.complete();
            }

            @Override
            public void onLoadMore() {
                //上拉加载更多,添加你加载数据的逻辑

                //加载完成时,隐藏控件上拉加载的状态
                refreshView.complete();
            }
        });

API扩充:

  1. 列表自动刷新
    如需进入页面后自动刷新列表数据,请在步骤3完成后添加:
        refreshView.setRefreshing(true);

  1. 无数据界面添加
    如果首次刷新无数据,需要显示无数据的占位图,可以在你加载完成时,根据后端接口返回的数据(一定是请求第一页且返回无数据的情况下)添加相应的占位图(上图gif中的“暂无数据”界面即控件中默认的,如果符合那恭喜你直接用即可,下面会写明调用方法。如果不符合你的审美或者和你的项目整体风格不一致,没关系,你只需把你的无数据占位图写好,api调用时当作参数传递即可,下面也会写明调用方法,很简单),并且依旧可以下拉刷新。
  • 直接用控件中的默认无数据占位图:
      refreshView.setEmptyView("暂无数据");

(注:默认的占位图界面文字显示也可以自己定义)

  • 使用自己写的无数据占位图(如customView),填入如下API的参数中
      refreshView.setCreateView(customView);

  1. 无网络或加载失败页添加
    如果项目中需要在无网络或者加载失败的情况下(根据接口数据返回)添加相应的ui给用户一个友好的交互,那么你可以直接调用,当然也可以写自己风格的ui,下面我会一一给出用法,并且依旧可以下拉刷新
    (ps:这里需要阐明一个逻辑问题,显示无网络界面或加载出错界面只能在你首次请求数据失败的情况下。why?试想如果你的用户已经加载出了一页数据,这时突然间没网络了或者刚好服务器出了点问题导致请求失败,你这时给用户显示一个网络出错页覆盖了已经有的数据,信不信,你家产品经历已经拿着40米的砍刀等着你跑39米。。还有一个提示的地方,有朋友说这个和无数据占位图没什么区别,其实区别在于一个是请求成功但是无数据,一个是请求失败)
  • 使用引入控件中的默认加载失败(无网络)占位图-效果如上图gif的重试界面
      refreshView.setErrorView();
  • 使用自己写的加载失败(无网络)占位图
    这里的重试按钮点击进行重新加载的过程你只需在你的点击事件中加入refreshView.setRefreshing(true);即可。用法:
      refreshView.setCreateView(errorView)

  1. 加载失败重试机制
    如果项目中需要支持加载失败时重试机制(这里指已经加载出数据但是在加载下一页数据失败时,点击底部变更的ui进行加载,详见上图gif加载更多时显示点击重试),当然控件也满足需求,调用时需要判断是否时大于第一页(注:有的公司接口规定从0开始,有的从1开始),这里还有一点要注意:如果当前不是首页的情况下加载失败,你需要将你的页码数减一,否则会跳过本页数据展示,用法如下:
     refreshView.onError();

为了便于理解,我贴出我项目的具体做法,并给出解释:

@Override
            public void onFail(TinaException exception) {
                if (m > 1) {
                    size = size - 1;
                    refreshView.onError();
                } else {
                    refreshView.setErrorView();
                }
                refreshView.complete();
            }

代码解释: onFail方法表示加载出错,m标记着是否是第一页数据(个人项目中请求页码从1开始),如果大于第一页时,页面数要减一,以保证数据不会遗漏加载。onError()方法处理了加载失败的ui显示和点击ui重新加载的机制。else里面代表当第一页数据加载失败时显示的占位。,complete():表示隐藏刷新的ui。项目最后会贴出项目demo地址,你可以自己再体会。


  1. 加载完成状态
    当所有数据加载加载完毕时,变更地步ui状态为"-- 没有更多了 --"
      refreshView.onNoMore();

下面是一些显示细节补充和实现

  1. 控件默认支持线性布局

  2. 变更下拉刷新的ui圆圈颜色
    refreshView.getSwipeRefreshLayout().setColorSchemeColors(getResources().getColor());

  3. 禁止下拉刷新
    refreshView.setRefreshEnable(false);

  4. 禁止加载更多
    refreshView.setLoadMoreEnable(false);

  5. 目前项目中不支持自动添加头部,如需实现添加头部,可在第一页返回数据中的第一个位置添加一条伪造数据,然后在adapter中添加多种item判断,如果position=0,则显示头部。(ps: 这样有个弊端:首页数据加载失败时,头部也显示不出来,其实也不太影响,如果一个上线项目数据一直加载失败,这后台该多大的锅),后面会把这部分缺失补充,敬请期待。

关于控件:

内部实现是通过SwipeRefreshLayout + recyclerView,通过将数据转换到控件内部的包装类WrapperAdapter获取数据进行加载更多的item包装。使用DataObserver来检测数据源的变化,来显示正常数据界面、无网络、无数据界面。

项目源码demo地址,如有帮助请star

ps : 由于无网络、无数据界面、还有加载重试机制在真实的情况下不好复现,为了所有情况都展示出来以便大家观看,因此demo中的数据是自己模拟的

闷骚代码男,码字不易,请抬起你的小手,点个赞呗~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,259评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,559评论 18 139
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,977评论 4 60
  • AMD规范是依赖前置, CMD规范是依赖后置 AMD规范的加载器会把所有的JS中的依赖前置执行。 CMD是懒加载,...
    大前端之路阅读 451评论 0 0
  • (2016.12.11-2017.3.20百日读50本书,百日码字30万(截止2016.12.10,简书上原存字3...
    叶两步阅读 689评论 4 37