纵观多数App,下拉刷新和上拉加载更多是很常见的功能,但是谷歌官方只有一个SwipeRefreshLayout用来下拉刷新,上拉加载更多还要自己做。
基于RecyclerView简单封装了这两个操作,下拉刷新支持LinearLayoutManager、GridLayoutManager和StaggeredGridLayoutManager;上拉加载更多只支持前两者。
话不多说先上效果图 数据来自干货集中营
(下拉刷新)
(上拉加载更多 – LinearLayoutManager)
(上拉加载更多 – GridLayoutManager)
(一) 使用方式,很简单 如下:
- 1. 下拉刷新 3步走
1.1 布局文件
1 | // 用SwipeRefreshLayout包裹RecyclerView |
1.2 给SwipeRefreshLayout
添加监听 增加触发刷新时的操作(比如重新请求数据)
1 | SwipeRefreshLayout swipeRefreshLayout = findViewById(); |
1.3 刷新操作(重新请求数据)完成后要回调来停止隐藏刷新动画(中上方圆形悬浮进度条旋转动画)
1 | swipeRefreshLayout.setRefreshing(false); |
至此下拉刷新完成
- 2.上拉加载3步走
2.1 初始化AdapterWrapper
和SwipeToLoadHelper
1 | // adapter是你自己为RecyclerView写的Adapter |
2.2 设置加载动作触发后的监听
1 | helper.setLoadMoreListener(new SwipeToLoadHelper.LoadMoreListener() { |
2.3 加载更多内容完成后要回调方法停止动画
1 | helper.setLoadMoreFinish() |
至此上拉加载完成 (注意更新数据时要调用AdapterWrapper.notifyDataSetChanged
)
(二) 简明扼要的实现思路(上拉加载操作)
RecyclerView
的itemView
的显示情况分为四种:
- 第1个可见的(部分显示或者完全显示都算可见)
- 第1个可见的且是完整的(完全显示算作完整的)
- 最后1个可见的
- 最后1个可见的且是完整的
- 1. 回弹效果
即手指抬起滑动停止,上拉加载更多
部分显示时,将上拉加载更多
滚动到不显示,使上面挨着它的itemView
为最后1个可见且是最后1个完整可见。
监听RecyclerView
的滚动,当RecyclerView
处于SCROLL_STATE_IDLE
状态时,获取最后1个完整可见的itemView
:如果是倒数第2个item
则计算该item
的下边距到RecyclerView
底部的距离deltaY
,然后将RecyclerView
向下滚动deltaY
;如果是上拉加载更多
则触发加载操作;其他情况不用处理。
1 | // 关键代码 rv : recyclerView |
- 2. 添加底部
加载更多
itemView
2.1 AdapterWrapper
重写了getItemCount
方法,保证得到itemView
的数量包括加载更多
。当是LinearLayoutManager
类型时直接加1;当是GridLayoutManager
类型时,如果需要则先将列表最后一行填满,再加1。比如:列表每行有3个itemView
,最后一行只有1个,这时就需要先加2,再加1,来保证加载更多
占据完整的一行。
1 | // 关键代码 其中的adapter为构造函数中传入的原生RecyclerView.Adapter |
2.2 AdapterWrapper
重写了getItemViewType
方法,当是最后一个位置时返回ITEM_TYPE_LOAD
1 | // 关键代码 |
2.3 AdapterWrapper
重写了onCreateViewHolder
方法,当类型为ITEM_TYPE_LOAD
时返回加载更多
的ViewHolder
,其他情况交给原生的adapter
处理。
1 | // 关键代码 |
2.4 AdapterWrapper
重写了onBindViewHolder
,这里有三种可能的情况:1. 正常的数据项itemView
,交给adapter
处理;2. GridView
的空白itemView
,隐藏处理;3. 底部的加载更多
,目前不需要做什么处理。
1 | // 关键代码 |
(三) 额外的两个说明
SwipeFreshLayout
有个setEnable(boolean)
方法,设置为false
的时候就下拉刷新功能就没有了,等同于普通的RecyclerView
- 同样
SwipeToLoadHelper
有个setSwipeToLoadEnabled(boolean)
方法,设置为false
的时候上拉加载功能就没有了, 等同于普通的RecyclerView
如有问题,欢迎指正~
附项目仓库地址,如有需要请自取~