智能刷新控件 SmartRefreshLayout:下拉刷新与上拉加载实战
下拉刷新 + 上拉加载是几乎所有列表页的标配。但 Android 官方只给了 SwipeRefreshLayout——功能简陋、不支持上拉加载、Header 无法定制。而 SmartRefreshLayout 是国内最流行、最成熟的刷新框架:强大稳定,集成了各种炫酷、多样、实用、美观的 Header 和 Footer,支持所有 View 与多层嵌套视图结构,并且继承自 ViewGroup 而非 FrameLayout/LinearLayout,性能更好。它还吸取了 SwipeRefreshLayout、Ultra-Pull-To-Refresh、TwinklingRefreshLayout 的优点。本文从依赖配置、三段式布局、刷新加载监听,到 RecyclerView 分页实战,带你完整掌握它。参考 GitHub 仓库 与 Gitee 中文镜像。
1、概述:SmartRefreshLayout 是什么
SmartRefreshLayout 以"打造一个强大、稳定、成熟的下拉刷新框架"为目标,名字里的"Smart"正体现在它的"智能"——它能自动识别内部内容是否可滚动、是否到达边界,从而正确触发下拉刷新和上拉加载,不需要开发者手动判断列表滚动位置。
维度 SmartRefreshLayout 官方 SwipeRefreshLayout
---------------------------------------------------------------
上拉加载 原生支持 不支持
Header/Footer 丰富多样、可自定义、可全局配置 只有官方一个固定样式
支持的内容 所有 View、多层嵌套 部分
继承自 ViewGroup(性能优) ViewGroup
越界回弹 支持 支持
核心实现(为什么用它):
1. 同时支持下拉刷新 + 上拉加载,官方 SwipeRefreshLayout 只能下拉
2. 内置几十种炫酷 Header/Footer(经典、Material、贝塞尔、水滴、凤凰、游戏…),还能自定义
3. "智能"识别内容边界——任意可滚动 View(RecyclerView/ScrollView/WebView…)放进去就能用
4. 继承 ViewGroup、支持多层嵌套,性能与扩展性都优于基于 FrameLayout 的同类库
2、依赖引入与全局默认配置
2.x 起,SmartRefreshLayout 拆分成多个 artifact 发布到 mavenCentral:核心包必引,Header/Footer 按需引入。类名包名仍是 com.scwang.smart.refresh.*。
// build.gradle (Module) —— 2.x,发布在 mavenCentral
dependencies {
// 核心包(必须)
implementation 'io.github.scwang90:refresh-layout-kernel:2.0.6'
// 经典 Header / Footer(按需)
implementation 'io.github.scwang90:refresh-header-classics:2.0.6'
implementation 'io.github.scwang90:refresh-footer-classics:2.0.6'
// 更多炫酷效果(按需)
implementation 'io.github.scwang90:refresh-header-material:2.0.6' // 谷歌 Material
implementation 'io.github.scwang90:refresh-header-radar:2.0.6' // 贝塞尔雷达
implementation 'io.github.scwang90:refresh-header-falsify:2.0.6' // 伪造(仅列表位移)
implementation 'io.github.scwang90:refresh-footer-ball:2.0.6' // 球脉冲
// 1.x 旧版为整包:com.scwang.smartrefresh:SmartRefreshLayout:1.1.0(已不推荐)
} SmartRefreshLayout 支持"全局默认 Header/Footer"——在 Application 静态代码块里配置一次,所有页面的 SmartRefreshLayout 都自动套用,不用每个 XML 写:
public class App extends Application {
// 静态块:全局默认 Header / Footer,所有页面生效
static {
SmartRefreshLayout.setDefaultRefreshHeaderCreator((context, layout) -> {
// 全局设置主题色(primary, accent)
layout.setPrimaryColorsId(R.color.purple_500, android.R.color.white);
return new ClassicsHeader(context); // 默认经典刷新头
});
SmartRefreshLayout.setDefaultRefreshFooterCreator((context, layout) ->
new ClassicsFooter(context).setSpinnerStyle(SpinnerStyle.Translate)); // 平移跟随
}
} 核心实现:
1. 2.x 拆包:refresh-layout-kernel 必引,header-/footer- 各效果包按需引入
2. 包名类名不变(com.scwang.smart.refresh.*),1.x 升 2.x 业务代码基本不动
3. 静态块里 setDefaultRefreshHeaderCreator/FooterCreator 设全局默认,省去每个页面重复配置
4. setPrimaryColorsId 统一主题色,setSpinnerStyle 控制 Footer 是"固定"还是"平移跟随"
3、XML 布局:Header + Content + Footer 三段式
SmartRefreshLayout 作为容器,内部是固定的"三段式"结构:① Header(刷新头)→ ② Content(内容)→ ③ Footer(加载尾),顺序不能乱,Content 只能有一个。
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/refreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- ① Header:下拉刷新头,放在内容之前 -->
<com.scwang.smart.refresh.header.ClassicsHeader
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- ② Content:实际内容,任意可滚动 View(RecyclerView/ScrollView/WebView…) -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- ③ Footer:上拉加载尾,放在内容之后 -->
<com.scwang.smart.refresh.footer.ClassicsFooter
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
核心实现:
1. 顺序固定:Header → Content → Footer,Content 是中间那个可滚动 View
2. Content 只能有一个;若配了全局默认 Header/Footer,XML 里可省略 Header/Footer 标签
3. Content 可以是任意 View,库会自动识别它是否可滚动、是否到顶/到底
4. Header/Footer 想换样式,直接替换标签类名(如 MaterialHeader、BezierRadarHeader)
4、刷新与加载监听 + finish 收尾
业务逻辑就两件事:监听下拉刷新和上拉加载,在数据回来后调 finish 结束状态。每个回调里都必须调用对应的 finish,否则刷新/加载状态不会自动收起。
SmartRefreshLayout refreshLayout = findViewById(R.id.refreshLayout);
// 下拉刷新
refreshLayout.setOnRefreshListener(refreshlayout -> {
loadFirstPage(); // 网络请求首页数据
// success=true 表示刷新成功;false 会显示"刷新失败"
refreshlayout.finishRefresh(/* success= */ true);
});
// 上拉加载更多
refreshLayout.setOnLoadMoreListener(refreshlayout -> {
loadNextPage();
refreshlayout.finishLoadMore(/* success= */ true);
});
// 变体:延时自动完成(模拟请求)
// refreshLayout.finishRefresh(2000); // 2 秒后结束刷新
// refreshLayout.finishLoadMoreWithNoMoreData(); // 加载到底,显示"没有更多数据" 核心实现:
1. setOnRefreshListener / setOnLoadMoreListener 分别监听下拉与上拉
2. 回调里必须调 finishRefresh / finishLoadMore,否则加载动画一直转
3. finishRefresh(boolean success):success=false 会展示"刷新失败",便于提示网络异常
4. finishLoadMoreWithNoMoreData() 标记"没有更多",Footer 变为"到底了",不再触发上拉
5、常用 API 与属性配置
除了监听,SmartRefreshLayout 还提供丰富的开关与触发 API,覆盖"禁用刷新、自动加载、越界回弹、主动触发"等场景:
// 启用 / 禁用
refreshLayout.setEnableRefresh(true); // 启用下拉刷新
refreshLayout.setEnableLoadMore(true); // 启用上拉加载
refreshLayout.setEnableAutoLoadMore(true); // 滚到底部自动加载(首次后自动关闭)
refreshLayout.setEnableOverScrollBounce(true); // 越界回弹(List/ScrollView 的橡皮筋效果)
// 主动触发
refreshLayout.autoRefresh(); // 代码触发下拉刷新(进页面自动刷新常用)
// 结束(可带延时 / 状态)
refreshLayout.finishRefresh(); // 立即结束
refreshLayout.finishRefresh(2000); // 延时 2 秒结束
refreshLayout.finishLoadMore(false); // 结束加载,false 表示本次失败
// 尺寸 / 触发比例
refreshLayout.setHeaderHeight(64); // Header 高度(dp)
refreshLayout.setFooterHeight(64);
refreshLayout.setHeaderTriggerRate(0.5f); // 下拉到 Header 高度的 50% 即触发
refreshLayout.setDragRate(0.5f); // 阻尼:手指移动 1,列表跟着移 0.5
核心实现:
1. setEnableRefresh/LoadMore 按页面需要开关;某些只读列表可 setEnableLoadMore(false)
2. autoRefresh() 用于"进入页面自动刷新",比手动下拉体验更主动
3. setHeaderTriggerRate 调"触发灵敏度",setDragRate 调"跟手感"(阻尼)
4. finishLoadMore(false) 区分"加载失败",finishLoadMoreWithNoMoreData() 区分"到底"
6、丰富的 Header 与 Footer 库
SmartRefreshLayout 最吸引人的就是它几十种开箱即用的炫酷 Header/Footer,换效果只需改 XML 标签或 Java 类名:
类型 类名 效果
------------------------------------------------------------------
经典 ClassicsHeader 文字 + 箭头/旋转进度
谷歌 MaterialHeader Material Design 水波
雷达 BezierRadarHeader 贝塞尔 + 雷达扫描
水滴 WaterDropHeader 仿 iOS 水滴回弹
球脉冲 BallPulseFooter 三球脉冲(加载尾常用)
凤凰 PhoenixHeader 烟花凤凰动画
飞行 TaurusHeader 飞行拖尾轨迹
打砖块 FunGameHitBlockHeader 游戏化刷新头
仓库 StoreHouseHeader storehouse 加载风格
伪造 FalsifyHeader 不显示控件,只让列表有位移
两级 TwoLevelHeader 二级刷新(仿淘宝二楼)
- 换效果:把 XML 里 ClassicsHeader 换成 MaterialHeader 即可,零成本切换
- 自定义:实现 RefreshHeader / RefreshFooter 接口,或继承 RefreshLayout 能完全自定义样式
- FalsifyHeader 适合"不想显示刷新头、只想要列表下拉位移手感"的场景
7、RecyclerView 完整实战:下拉刷新 + 上拉加载分页
把前面几节串起来,实现一个完整的分页列表:下拉刷新重置第 1 页,上拉加载下一页,加载到底显示"没有更多"。
public class RefreshActivity extends AppCompatActivity {
private SmartRefreshLayout refreshLayout;
private RecyclerView recyclerView;
private SimpleAdapter adapter;
private final List<String> data = new ArrayList<>();
private int page = 1;
private static final int MAX_PAGE = 5; // 模拟共 5 页数据
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_refresh);
refreshLayout = findViewById(R.id.refreshLayout);
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new SimpleAdapter(data);
recyclerView.setAdapter(adapter);
// 下拉刷新 = 加载第 1 页
refreshLayout.setOnRefreshListener(layout -> load(1));
// 上拉加载 = 下一页
refreshLayout.setOnLoadMoreListener(layout -> load(page + 1));
refreshLayout.autoRefresh(); // 进入页面自动触发刷新
}
private void load(int targetPage) {
// 模拟网络请求延迟
recyclerView.postDelayed(() -> {
if (targetPage == 1) {
data.clear();
data.addAll(generatePage(1));
page = 1;
refreshLayout.finishRefresh(true);
} else if (targetPage <= MAX_PAGE) {
data.addAll(generatePage(targetPage));
page = targetPage;
refreshLayout.finishLoadMore(true);
} else {
// 超过最大页,标记没有更多
refreshLayout.finishLoadMoreWithNoMoreData();
}
adapter.notifyDataSetChanged();
}, 1500);
}
// 生成某一页的模拟数据
private List<String> generatePage(int p) {
List<String> list = new ArrayList<>();
for (int i = 1; i <= 20; i++) {
list.add("第 " + p + " 页 - 条目 " + i);
}
return list;
}
} 核心实现:
1. 下拉刷新回调里加载第 1 页,先 clear 再 add,最后 finishRefresh(true)
2. 上拉加载回调里加载 page+1;超过最大页用 finishLoadMoreWithNoMoreData() 标记到底
3. onCreate 末尾 autoRefresh(),进入页面即自动拉取首屏,无需用户手动下拉
4. 数据更新后 adapter.notifyDataSetChanged()(或更优的 notifyItemRangeInserted)刷新列表
8、总结
SmartRefreshLayout 把下拉刷新 + 上拉加载做成了"开箱即用 + 高度可定制"的工业级方案。它的三段式结构、智能边界识别、丰富的 Header/Footer,让"刷新加载"这件事几乎零心智负担。
关键要点:
- 三段式:Header → Content → Footer,Content 是唯一的可滚动内容
- 监听:setOnRefreshListener / setOnLoadMoreListener,回调里必须 finishRefresh/finishLoadMore
- 全局默认:Application 静态块设 setDefaultRefreshHeaderCreator/FooterCreator,统一风格
- 2.x 拆包:refresh-layout-kernel 必引,header-/footer- 按需;包名仍为 com.scwang.smart.refresh.*
- Header/Footer 几十种可换,FalsifyHeader 适合只想要位移手感的场景
- 注意:Content 必须是可滚动 View;autoRefresh 进页自动刷新;finishLoadMoreWithNoMoreData 标记到底
对于做资讯、商品、动态、消息等几乎所有含列表页的开发者而言,掌握 SmartRefreshLayout 的"三段式布局 + 刷新加载监听 + 全局默认配置"是必要的——它是 Android 刷新领域事实上的标准轮子,能让你用一个控件就同时搞定下拉刷新、上拉加载、到底提示、越界回弹,还能随时切换几十种炫酷 Header。把第 7 节那套分页 Adapter 模板记牢,遇到列表页几乎可以秒级落地。