Android RecyclerView上拉加载更多功能回弹实现代码
发布时间 - 2026-01-10 23:01:36 点击率:次实现原理是使用RecyclerView的OnTouchListener方法监听滑动 在adapter里面增加两项footview 其中date.size为显示的加载条,可以自定义,date.size+1为空白的View,我们设置其高度为0 我们通过LinearLayoutManager的 findLastVisibleItemPosition判断显示的最后一条数据,如果是空白view,表示加载条已经完全展示,松开即可刷新。

回弹效果是通过在滑动时动态改变空白view的高度,达到阻尼效果 ,回弹时再动态将其改为0,达到回弹效果,通过loading防止加载过程中滑动导致显示问题 这里的回调采用了Runnable传参
public class RefreshFootAdapter extends
RecyclerView.Adapter<RecyclerView.ViewHolder> {
// 上拉加载更多
public static final int SATUS_PULLUP_LOAD_MORE = 0;
// 正在加载中
public static final int SATUS_LOADING_MORE = 1;
public static final int SATUS_UP_LOADING_MORE = 2;
// 上拉加载更多状态-默认为0
private int load_more_status = 0;
private LayoutInflater mInflater;
private List<String> mTitles = null;
private static final int TYPE_ITEM = 0; // 普通Item View
private static final int TYPE_FOOTER = 1; // 底部FootView
private static final int TYPE_FOOTER_EMPTY = 2; // 底部空白View
private static int pagesize;
private int eview_height = 1;
private long TimeFlag;// 回弹时间
private RecyclerView parent;
private boolean loadmare;// 判断当前是可加载更多
private boolean loading;// 判断是否正在加载
private int startY, nowY;// 滑动判断
<span style="white-space:pre"> </span>//构造函数 处理滑动监听 更新等功能
public RefreshFootAdapter(Context context, RecyclerView parent,
final LinearLayoutManager linearLayoutManager, int pagesize,
final Runnable onloadmore) {
this.parent = parent;
this.mInflater = LayoutInflater.from(context);
this.mTitles = new ArrayList<String>();
for (int i = 0; i < 20; i++) {
int index = i + 1;
mTitles.add("item" + index);
}
this.pagesize = pagesize;
parent.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent ev) {
// TODO Auto-generated method stub
switch (ev.getAction()) {
case MotionEvent.ACTION_MOVE:
nowY = (int) ev.getY();
if (RefreshFootAdapter.this.getItemCount() == linearLayoutManager
.findLastVisibleItemPosition() + 1) {
if (startY == 0) {// 按下
startY = nowY;
}
int changeY = nowY - startY;
RefreshFootAdapter.this
.notifyEmptyView((int) (-changeY / 1.3f));
if (loading) {
return false;
}
RefreshFootAdapter.this
.changeMoreStatus(RefreshFootAdapter.this.SATUS_UP_LOADING_MORE);
loadmare = true;
} else {
loadmare = false;
if (loading) {
return false;
}
RefreshFootAdapter.this
.changeMoreStatus(RefreshFootAdapter.this.SATUS_PULLUP_LOAD_MORE);
// 普通的滑动
startY = 0;
}
break;
case MotionEvent.ACTION_UP:
RefreshFootAdapter.this.resetEmptyView();
if (loadmare) {
if (loading) {
return false;
} else {
RefreshFootAdapter.this
.changeMoreStatus(RefreshFootAdapter.this.SATUS_LOADING_MORE);
if (onloadmore != null && !loading) {
loading = true;
onloadmore.run();
}
}
}
startY = 0;
break;
default:
break;
}
return false;
}
});
}
/**
* item显示类型
*
* @param parent
* @param viewType
* @return
*/
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// 进行判断显示类型,来创建返回不同的View
if (viewType == TYPE_ITEM) {
View view = mInflater.inflate(R.layout.item_recycler_layout,
parent, false);
// 这边可以做一些属性设置,甚至事件监听绑定
// view.setBackgroundColor(Color.RED);
ItemViewHolder itemViewHolder = new ItemViewHolder(view);
return itemViewHolder;
} else if (viewType == TYPE_FOOTER) {
View foot_view = mInflater.inflate(
R.layout.recycler_load_more_layout, parent, false);
// 这边可以做一些属性设置,甚至事件监听绑定
// view.setBackgroundColor(Color.RED);
FootViewHolder footViewHolder = new FootViewHolder(foot_view);
return footViewHolder;
} else if (viewType == TYPE_FOOTER_EMPTY) {
View foot_view_empty = mInflater.inflate(
R.layout.recycler_load_more_layout_empty, parent, false);
// 这边可以做一些属性设置,甚至事件监听绑定
// view.setBackgroundColor(Color.RED);
FootEmptyHolder footEmptyViewHolder = new FootEmptyHolder(
foot_view_empty);
return footEmptyViewHolder;
}
return null;
}
/**
* 数据的绑定显示
*
* @param holder
* @param position
*/
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof ItemViewHolder) {
((ItemViewHolder) holder).item_tv.setText(mTitles.get(position));
holder.itemView.setTag(position);
} else if (holder instanceof FootViewHolder) {
FootViewHolder footViewHolder = (FootViewHolder) holder;
switch (load_more_status) {
case SATUS_PULLUP_LOAD_MORE:
footViewHolder.foot_view_item_tv.setText("上拉加载更多...");
break;
case SATUS_LOADING_MORE:
footViewHolder.foot_view_item_tv.setText("正在加载更多数据...");
break;
case SATUS_UP_LOADING_MORE:
footViewHolder.foot_view_item_tv.setText("松开加载更多数据...");
break;
}
} else if (holder instanceof FootEmptyHolder) {
FootEmptyHolder footViewHolder = (FootEmptyHolder) holder;
footViewHolder.empty.setLayoutParams(new ViewGroup.LayoutParams(
111, eview_height));
}
}
/**
* 进行判断是普通Item视图还是FootView视图
*
* @param position
* @return
*/
@Override
public int getItemViewType(int position) {
// 最后一个item设置为footerView
if (position + 1 == getItemCount()) {
return TYPE_FOOTER_EMPTY;
} else if (position + 2 == getItemCount()) {
return TYPE_FOOTER;
} else {
return TYPE_ITEM;
}
}
<span style="white-space:pre"> </span>//如果是页数的倍数 itemcount+2
@Override
public int getItemCount() {
if (mTitles.size() % pagesize != 0) {
return mTitles.size();
} else {
return mTitles.size() + 2;
}
// return mTitles.size()+1;
}
// 自定义的ViewHolder,持有每个Item的的所有界面元素
public static class ItemViewHolder extends RecyclerView.ViewHolder {
public TextView item_tv;
public ItemViewHolder(View view) {
super(view);
item_tv = (TextView) view.findViewById(R.id.item_tv);
}
}
/**
* 底部FootView布局
*/
public static class FootViewHolder extends RecyclerView.ViewHolder {
private TextView foot_view_item_tv;
public FootViewHolder(View view) {
super(view);
foot_view_item_tv = (TextView) view
.findViewById(R.id.foot_view_item_tv);
}
}
<span style="white-space:pre"> </span>//空白项
public static class FootEmptyHolder extends RecyclerView.ViewHolder {
private View empty;
public FootEmptyHolder(View view) {
super(view);
empty = view.findViewById(R.id.empty);
}
}
// 添加数据
public void addItem(List<String> newDatas) {
// mTitles.add(position, data);
// notifyItemInserted(position);
newDatas.addAll(mTitles);
mTitles.removeAll(mTitles);
mTitles.addAll(newDatas);
notifyDataSetChanged();
}
<span style="white-space:pre"> </span>//更新添加数据
public void addMoreItem(List<String> newDatas) {
mTitles.addAll(newDatas);
notifyDataSetChanged();
}
<span style="white-space:pre"> </span>//更新空白项高度
private void notifyEmptyView(int height) {
this.eview_height = height;
notifyItemChanged(getItemCount() - 1);
}
<span style="white-space:pre"> </span>//空白回弹 伪回弹动画
private void resetEmptyView() {
final int dx = eview_height;
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
final int time = 500;
final long startTime = new Date().getTime();
TimeFlag = startTime;
long nowTime = new Date().getTime();
while (startTime + time > nowTime && TimeFlag == startTime) {
nowTime = new Date().getTime();
final int dt = (int) (nowTime - startTime);
parent.post(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
eview_height = eview_height * (time - dt) / time;
notifyDataSetChanged();
}
});
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
parent.post(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
eview_height = 0;
notifyDataSetChanged();
}
});
}
}).start();
}
<span style="white-space:pre"> </span>//停止加载更多 重置loading状态和显示文本
public void stopLoadMore() {
notifyDataSetChanged();
loading = false;
RefreshFootAdapter.this
.changeMoreStatus(RefreshFootAdapter.this.SATUS_PULLUP_LOAD_MORE);
}
//改变加载条状态
private void changeMoreStatus(int status) {
if (loading) {
return;
}
load_more_status = status;
notifyDataSetChanged();
}
}
图1为滑动过程
图2为松开加载
以上所述是小编给大家介绍的Android RecyclerView上拉加载更多功能回弹实现代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
# recyclerview上拉加载
# recyclerview实现回弹
# Android ScrollView的顶部下拉和底部上拉回弹效果
# android仿QQ个人主页下拉回弹效果
# Android界面上拉下拉的回弹效果实例代码
# Android ReboundScrollView仿IOS拖拽回弹效果
# Android仿IOS回弹效果 支持任何控件
# Android ScrollView实现横向和竖向拖动回弹效果
# Android自定义ScrollView实现放大回弹效果
# Android编程ViewPager回弹效果实例分析
# Android自定义控件仿ios下拉回弹效果
# Android基于reclyview实现列表回弹动画效果
# 加载
# 绑定
# 自定义
# 小编
# 正在加载
# 在此
# 将其
# 采用了
# 给大家
# 按下
# 等功能
# 设置为
# 两项
# 已经完全
# 所述
# 回调
# 给我留言
# 感谢大家
# 过程中
# 时再
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
使用豆包 AI 辅助进行简单网页 HTML 结构设计
详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)
今日头条微视频如何找选题 今日头条微视频找选题技巧【指南】
千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】
Laravel Eloquent模型如何创建_Laravel ORM基础之Model创建与使用教程
如何登录建站主机?访问步骤全解析
JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)
laravel怎么为API路由添加签名中间件保护_laravel API路由签名中间件保护方法
php 三元运算符实例详细介绍
如何快速搭建支持数据库操作的智能建站平台?
深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?
javascript和jQuery中的AJAX技术详解【包含AJAX各种跨域技术】
WEB开发之注册页面验证码倒计时代码的实现
Laravel项目怎么部署到Linux_Laravel Nginx配置详解
制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?
如何在自有机房高效搭建专业网站?
Laravel如何使用Contracts(契约)进行编程_Laravel契约接口与依赖反转
C++用Dijkstra(迪杰斯特拉)算法求最短路径
如何解决hover在ie6中的兼容性问题
如何快速查询域名建站关键信息?
MySQL查询结果复制到新表的方法(更新、插入)
网站优化排名时,需要考虑哪些问题呢?
北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?
如何打造高效商业网站?建站目的决定转化率
如何获取上海专业网站定制建站电话?
专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?
android nfc常用标签读取总结
Laravel如何与Inertia.js和Vue/React构建现代单页应用
浅析上传头像示例及其注意事项
微信小程序 scroll-view组件实现列表页实例代码
教学论文网站制作软件有哪些,写论文用什么软件
?
JS经典正则表达式笔试题汇总
悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤
Claude怎样写结构化提示词_Claude结构化提示词写法【教程】
如何快速搭建FTP站点实现文件共享?
Laravel如何配置中间件Middleware_Laravel自定义中间件拦截请求与权限校验【步骤】
如何快速完成中国万网建站详细流程?
利用vue写todolist单页应用
Laravel如何使用集合(Collections)进行数据处理_Laravel Collection常用方法与技巧
详解Nginx + Tomcat 反向代理 如何在高效的在一台服务器部署多个站点
Laravel如何实现事件和监听器?(Event & Listener实战)
Laravel怎么集成Log日志记录_Laravel单文件与每日日志配置及自定义通道【详解】
java中使用zxing批量生成二维码立牌
高端网站建设与定制开发一站式解决方案 中企动力
Laravel怎么调用外部API_Laravel Http Client客户端使用
Laravel如何实现数据库事务?(DB Facade示例)
如何快速搭建高效香港服务器网站?
laravel怎么通过契约(Contracts)编程_laravel契约(Contracts)编程方法
使用C语言编写圣诞表白程序
Laravel怎么配置.env环境变量_Laravel生产环境敏感数据保护与读取【方法】

