介绍
一个功能强大的下拉刷新和加载更多组件,支持自定义刷新样式、空页面展示、加载更多状态、头布局和尾布局。组件内置了基础的刷新动画、状态管理和数据管理,可以轻松实现列表的刷新和加载功能。
功能特点
- 支持下拉刷新与上拉加载更多功能
- 支持分页加载和数据管理
- 适配List/Grid/ScrollView/WaterFlow四种布局类型,也可以自行实现
- 内置空布局视图:可传入空布局参数改变空布局样式
- 支持自定义空布局
- 支持自定义刷新样式和加载更多样式
- 头部/尾部扩展:支持自定义Header/Footer布局
- 支持页面数据不满一屏时自动触发上拉加载(需要手动开启)
- 支持数据分组,支持吸顶/吸尾
- 支持侧滑功能,包括左侧滑/右侧滑
- 兼容 V2 状态(该控件是 V2 控件)
链接
源码
示例
效果图








下载安装
在每个har/hsp模块中,通过ohpm工具下载安装库:
ohpm install @hzw/zrefresh
使用方法
基本使用示例
// BaseRefreshController用于更新刷新状态
@Local controller: BaseRefreshController = new BaseRefreshController()
// BaseRefreshDataSource用于更新数据
@Local data: BaseRefreshDataSource<String> = new BaseRefreshDataSource<String>()
aboutToAppear() {
this.controller.autoRefresh()
}
BaseRefresh({
data: this.data, // 设置数据源
controller: this.controller, // 设置状态管理
type: BaseRefreshType.List, // 刷新内容类型,默认为滚动布局
onRefresh: this.onRefresh, // 设置下拉刷新回调
onLoadMore: this.onLoadMore, // 设置加载更多回调
pageSize: 10, // 设置每页加载数量
refreshModifier: new RefreshModifier(), // 设置Refresh样式
listModifier: new ListModifier(), // 设置列表样式
isShowHeader: false, // 设置是否显示头部布局
isShowFooter: false, // 设置是否显示底部布局
emptyStatus: {}, // 设置默认空布局样式,如果设置了,则数据为空时会显示默认布局
customEmptyView: () => { // 设置自定义空布局,如果设置了,则数据为空时会显示自定义布局
this.Empty()
},
customHeadView: () => { // 设置自定义头部布局
this.Head()
},
customFootView: () => { // 设置自定义底部布局
this.Footer()
},
customRefreshHeadView: () => { // 自定义刷新头布局
this.RefreshHead()
},
customRefreshFootView: () => { // 自定义底部加载更多布局
this.RefreshFoot()
},
builder: () => { // 内容
this.Content()
},
})
相关方法
触发刷新
// this.controller 是 BaseRefreshController 的实例
this.controller.autoRefresh()
添加数据
// this.data 是 BaseRefreshDataSource 的实例
this.data.complete(moreData)
结束下拉刷新/结束加载更多
this.controller.finishRefresh()
// 根据数据数量判断是否没有更多数据
const data = ["1", "2"]
this.controller.finishRefresh(data)
// 也可以传入参数来手动设置是否没有更多数据
this.controller.finishRefresh(noMore)
结束下拉刷新
this.controller.finishRefresh()
// 根据数据数量判断是否没有更多数据
const data = ["1", "2"]
this.controller.finishRefresh(data)
// 也可以传入参数来手动设置是否没有更多数据
this.controller.finishRefresh(noMore)
结束加载更多
this.controller.finishLoadMore()
// 根据数据数量判断是否没有更多数据
const data = ["1", "2"]
this.controller.finishLoadMore(data)
// 也可以传入参数来手动设置是否没有更多数据
this.controller.finishLoadMore(noMore)
空页面显示隐藏,不传默认显示
this.controller.showEmpty(visible)
头布局显示隐藏,不传默认显示
this.controller.showHead(visible)
底布局显示隐藏,不传默认显示
this.controller.showFoot(visible)
底部加载更多布局显示隐藏,不传默认显示
this.controller.showRefreshFooter(visible)
重置状态
this.controller.resetStatus()
关于 List(列表) 的刷新示例,通过BaseRefreshController的实例的complete()方法设置数据
@ComponentV2
export struct RefreshListDemo {
@Local controller: BaseRefreshController = new BaseRefreshController()
@Local data: BaseRefreshDataSource<String> = new BaseRefreshDataSource<String>()
@Local emptyData: boolean = false
@Local pageSize: number = 15
aboutToAppear() {
this.controller.autoRefresh()
}
onRefresh = () => {
this.loadData()
}
onLoadMore = () => {
this.loadData()
}
loadData() {
setTimeout(() => {
if (this.emptyData) {
this.data.complete([])
this.controller.finishState([])
return
}
const arr: number[] = []
const start = (this.controller.pageIndex - 1) * this.pageSize
if (this.controller.pageIndex == 2) {
for (let i = start; i < start + 5; i++) {
arr.push(i)
}
} else {
for (let i = start; i < start + this.pageSize; i++) {
arr.push(i)
}
}
const result = Array.from(arr, (item, i) => `Item ${item + 1}`)
this.data.complete(result)
this.controller.finishState(result)
return undefined
}, 700)
}
build() {
BaseRefresh({
data: this.data, // 设置数据源
controller: this.controller, // 设置状态管理
type: BaseRefreshType.List, // 刷新内容类型,默认为滚动布局,当前设置为列表类型
onRefresh: this.onRefresh, // 设置下拉刷新回调
onLoadMore: this.onLoadMore, // 设置加载更多回调
pageSize: this.pageSize, // 设置每页加载数量
refreshModifier: new RefreshModifier(), // 设置Refresh样式
listModifier: new ListModifier(), // 设置列表样式
builder: () => { // 内容
this.Content()
},
})
}
@Builder
Content() {
LazyForEach(this.data, (item: string) => {
ListItem() {
Stack() {
Text(`${item}`)
.borderRadius(10)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
.width('100%')
.height('100%')
.textAlign(TextAlign.Center)
.backgroundColor(Color.Blue)
}
.width('100%')
.height(100)
.padding({ left: 10, right: 10, top: 10 })
}
}, (item: string, index: number) => `${item}${index}`)
}
}
关于 Scroll(滚动) 的刷新示例
@ComponentV2
export struct RefreshScrollDemo {
@Local controller: BaseRefreshController = new BaseRefreshController()
@Local emptyData: boolean = false
aboutToAppear() {
this.controller.autoRefresh()
}
onRefresh = () => {
this.loadData()
}
onLoadMore = () => {
this.loadData()
}
loadData() {
setTimeout(() => {
this.controller.showEmpty(this.emptyData)
this.controller.finishRefresh()
return undefined
}, 700)
}
build() {
Column() {
OperateView({
controller: this.controller,
emptyData: this.emptyData!!
})
BaseRefresh({
controller: this.controller, // 设置状态管理
type: BaseRefreshType.ScrollView, // 刷新内容类型,默认为滚动布局,当前设置为滚动类型
onRefresh: this.onRefresh, // 设置下拉刷新回调
onLoadMore: this.onLoadMore, // 设置加载更多回调
refreshModifier: new RefreshModifier(), // 设置Refresh样式
scrollModifier: new ScrollModifier(), // 设置滚动样式
isShowHeader: false, // 设置是否显示头部布局
isShowFooter: false, // 设置是否显示底部布局
emptyStatus: {}, // 设置默认空布局样式,如果设置了,则数据为空时会显示默认布局
customEmptyView: () => { // 设置自定义空布局,如果设置了,则数据为空时会显示自定义布局
this.Empty()
},
customHeadView: () => { // 设置自定义头部布局
this.Head()
},
customFootView: () => { // 设置自定义底部布局
this.Footer()
},
customRefreshHeadView: () => { // 自定义刷新头布局
this.RefreshHead()
},
customRefreshFootView: () => { // 自定义底部加载更多布局
this.RefreshFoot()
},
builder: () => { // 内容
this.Content()
},
})
.width('100%')
.layoutWeight(1)
}
.width('100%')
.height('100%')
.backgroundColor(Color.White)
}
@Builder
Content() {
Stack() {
Text(`滚动内容`)
.borderRadius(10)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
.width('100%')
.height('120%')
.textAlign(TextAlign.Center)
.backgroundColor(Color.Orange)
}
.padding({ left: 10, right: 10, top: 10 })
}
@Builder
Empty() {
CustomEmpty()
}
@Builder
Head() {
CustomHead()
}
@Builder
Footer() {
CustomFooter()
}
@Builder
RefreshHead() {
CustomRefreshHead()
}
@Builder
RefreshFoot() {
CustomRefreshFoot({ showEnd: this.controller.showEnd })
}
}
关于 Grid(网格) 的刷新示例
@ComponentV2
export struct RefreshGridDemo {
@Local controller: BaseRefreshController = new BaseRefreshController()
@Local data: BaseRefreshDataSource<String> = new BaseRefreshDataSource<String>()
@Local emptyData: boolean = false
@Local col: number = 2
@Local pageSize: number = 15
@Computed
get colStr() {
const arr: string[] = []
for (let i = 0; i < this.col; i++) {
arr.push('1fr')
}
return arr.join(' ')
}
aboutToAppear() {
this.controller.autoRefresh()
}
onRefresh = () => {
this.loadData()
}
onLoadMore = () => {
this.loadData()
}
loadData() {
setTimeout(() => {
if (this.emptyData) {
this.data.complete([])
this.controller.finishState([])
return
}
const arr: number[] = []
const start = (this.controller.pageIndex - 1) * this.pageSize
if (this.controller.pageIndex == 2) {
for (let i = start; i < start + 5; i++) {
arr.push(i)
}
} else {
for (let i = start; i < start + this.pageSize; i++) {
arr.push(i)
}
}
const result = Array.from(arr, (item, i) => `Item ${item + 1}`)
this.data.complete(result)
this.controller.finishState(result)
return undefined
}, 700)
}
build() {
BaseRefresh({
data: this.data, // 设置数据源
controller: this.controller, // 设置状态管理
type: BaseRefreshType.Grid, // 刷新内容类型,默认为滚动布局,当前设置为网格类型
onRefresh: this.onRefresh, // 设置下拉刷新回调
onLoadMore: this.onLoadMore, // 设置加载更多回调
pageSize: this.pageSize, // 设置每页加载数量
refreshModifier: new RefreshModifier(), // 设置Refresh样式
gridModifier: new GridModifier().columnsTemplate(this.colStr), // 设置网格样式
builder: () => { // 内容
this.Content()
},
})
}
@Builder
Content() {
LazyForEach(this.data, (item: string) => {
GridItem() {
Stack() {
Text(`${item}`)
.borderRadius(10)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
.width('100%')
.height('100%')
.textAlign(TextAlign.Center)
.backgroundColor(Color.Blue)
}
.width('100%')
.height(100)
.padding({ left: 10, right: 10, top: 10 })
}
}, (item: string, index: number) => `${item}${index}`)
}
}
关于 WaterFlow(瀑布流) 的刷新示例
@ComponentV2
export struct RefreshWaterFlowDemo {
@Local controller: BaseRefreshController = new BaseRefreshController()
@Local data: BaseRefreshDataSource<String> = new BaseRefreshDataSource<String>()
@Local emptyData: boolean = false
@Local col: number = 2
@Local pageSize: number = 15
@Computed
get colStr() {
const arr: string[] = []
for (let i = 0; i < this.col; i++) {
arr.push('1fr')
}
return arr.join(' ')
}
aboutToAppear() {
this.controller.autoRefresh()
}
onRefresh = () => {
this.loadData()
}
onLoadMore = () => {
this.loadData()
}
loadData() {
setTimeout(() => {
if (this.emptyData) {
this.data.complete([])
this.controller.finishState([])
return
}
const arr: number[] = []
const start = (this.controller.pageIndex - 1) * this.pageSize
if (this.controller.pageIndex == 2) {
for (let i = start; i < start + 5; i++) {
arr.push(i)
}
} else {
for (let i = start; i < start + this.pageSize; i++) {
arr.push(i)
}
}
const result = Array.from(arr, (item, i) => `Item ${item + 1}`)
this.data.complete(result)
this.controller.finishState(result)
return undefined
}, 700)
}
build() {
BaseRefresh({
data: this.data, // 设置数据源
controller: this.controller, // 设置状态管理
type: BaseRefreshType.WaterFlow, // 刷新内容类型,默认为滚动布局,当前设置为瀑布流类型
onRefresh: this.onRefresh, // 设置下拉刷新回调
onLoadMore: this.onLoadMore, // 设置加载更多回调
pageSize: this.pageSize, // 设置每页加载数量
refreshModifier: new RefreshModifier(), // 设置Refresh样式
scrollModifier: new ScrollModifier(), // 设置滚动样式,因为瀑布流类型是 Scroll嵌套WaterFlow来实现头尾布局,所以用到了Scroll控件
waterFlowModifier: new WaterFlowModifier().columnsTemplate(this.colStr), // 设置瀑布流样式
builder: () => { // 内容
this.Content()
},
})
}
@Builder
Content() {
LazyForEach(this.data, (item: string, index: number) => {
FlowItem() {
Stack() {
Text(`${item}`)
.borderRadius(10)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
.width('100%')
.height('100%')
.textAlign(TextAlign.Center)
.backgroundColor(Color.Blue)
}
.height(Math.random() * 100 + 100)
.padding({ left: 10, right: 10, top: 10 })
}
.width('100%')
}, (item: string, index: number) => `${item}${index}`)
}
}
关于 No(不指定滚动布局类型,自行实现) 的刷新示例
@ComponentV2
export struct RefreshNoDemo {
@Local controller: BaseRefreshController = new BaseRefreshController()
@Local emptyData: boolean = false
aboutToAppear() {
this.controller.autoRefresh()
}
onRefresh = () => {
this.loadData()
}
onLoadMore = () => {
this.loadData()
}
loadData() {
setTimeout(() => {
this.controller.showEmpty(this.emptyData)
this.controller.finishRefresh()
return undefined
}, 700)
}
build() {
BaseRefresh({
controller: this.controller, // 设置状态管理
type: BaseRefreshType.No, // 刷新内容类型,无滚动类型(不内置滚动控件,交由使用者自定义)
onRefresh: this.onRefresh, // 设置下拉刷新回调
onLoadMore: this.onLoadMore, // 设置加载更多回调
refreshModifier: new RefreshModifier(), // 设置Refresh样式
scrollModifier: new ScrollModifier(), // 设置滚动样式
builder: () => { // 内容
this.Content()
},
})
}
@Builder
Content() {
Scroll() {
Stack() {
Text(`滚动内容`)
.borderRadius(10)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
.width('100%')
.height('120%')
.textAlign(TextAlign.Center)
.backgroundColor(Color.Orange)
}
.padding({ left: 10, right: 10, top: 10 })
}
}
}
参数说明
BaseRefresh 组件参数
参数名 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
data | BaseAbsRefreshDataSource | undefined | undefined | 是 | 数据源,需继承BaseAbsRefreshDataSource |
type | BaseRefreshType | ScrollView | 否 | 内容类型:List/ScrollView/Grid/WaterFlow/No |
enableRefresh | boolean | true | 否 | 是否启用下拉刷新 |
enableLoadMore | boolean | true | 否 | 是否启用加载更多 |
pageSize | number | 20 | 否 | 每页加载数量 |
controller | BaseRefreshController | new BaseRefreshController() | 是 | 状态控制器 |
scroller | Scroller | new Scroller() | 是 | 滚动控制器实例 |
refreshModifier | RefreshModifier | new RefreshModifier() | 否 | 刷新控件样式配置 |
listModifier | ListModifier | new ListModifier() | 否 | 列表样式配置 |
scrollModifier | ScrollModifier | new ScrollModifier() | 否 | 滚动视图样式配置 |
gridModifier | GridModifier | new GridModifier() | 否 | 网格布局样式配置 |
waterFlowModifier | WaterFlowModifier | new WaterFlowModifier() | 否 | 瀑布流样式配置 |
listItemModifier | ListItemModifier | new ListItemModifier() | 否 | 列表项样式配置(需设置listBuilder生效) |
onRefresh | () => Promise<Object[]|undefined> | async () => {} | 是 | 下拉刷新回调函数 |
onLoadMore | () => Promise<Object[]|undefined> | async () => {} | 是 | 加载更多回调函数 |
builder | () => void | this.doBuilder | 是 | 内容构建函数 |
listBuilder | (data: Object, index: number) => void | undefined | 否 | 列表项构建函数(设置后builder属性失效) |
swipeLeftBuilder | (data: Object, index: number) => void | undefined | 否 | 列表项左滑布局(需设置listBuilder生效) |
swipeRightBuilder | (data: Object, index: number) => void | undefined | 否 | 列表项右滑布局(需设置listBuilder生效) |
isShowHeader | boolean | false | 否 | 是否显示头部布局 |
isShowFooter | boolean | false | 否 | 是否显示底部布局 |
isShowRefreshFooter | boolean | true | 否 | 是否显示加载更多布局 |
groupData | BaseAbsRefreshDataSource | undefined | undefined | 是 | 分组数据源(需设置listBuilder生效) |
listItemGroupModifier | ListItemGroupModifier | new ListItemGroupModifier() | 否 | 列表项分组样式配置(需设置listBuilder和groupData生效) |
listItemGroupHeadBuilder | (data: BaseRefreshGroupItem, index: number) => void | undefined | 否 | 列表分组头部构建函数(需设置listBuilder和groupData生效) |
listItemGroupFootBuilder | (data: BaseRefreshGroupItem, index: number) => void | undefined | 否 | 列表分组底部构建函数(需设置listBuilder和groupData生效) |
groupStyle | ListItemGroupStyle | undefined | undefined | 否 | 列表分组样式配置(需设置listBuilder和groupData生效) |
isGroupTopSticky | boolean | true | 否 | 列表分组是否顶部吸顶(需设置listBuilder和groupData生效) |
isGroupFootSticky | boolean | false | 否 | 列表分组是否底部吸顶(需设置listBuilder和groupData生效) |
isAutoLoadMoreWhileNoFull | boolean | false | 否 | 页面数据不满一屏时是否自动触发上拉加载 |
customEmptyView | () => void | undefined | 否 | 自定义空布局组件 |
customHeadView | () => void | undefined | 否 | 自定义头部布局 |
customFootView | () => void | undefined | 否 | 自定义底部布局 |
customRefreshHeadView | () => void | undefined | 否 | 自定义刷新头部组件 |
customRefreshFootView | () => void | undefined | 否 | 自定义加载底部组件 |
emptyStatus | BaseRefreshEmptyStatus | undefined | undefined | 否 | 空布局状态配置 |
gridLayoutOptions | GridLayoutOptions | undefined | undefined | 否 | 网格布局配置选项 |
BaseRefreshController 类方法
方法名 | 参数 | 返回值 | 说明 |
---|---|---|---|
autoRefresh | - | void | 自动触发刷新 |
finishState | noMore: (Object | undefined | null)[] | undefined | null | boolean | void | 根据当前状态结束刷新/加载 |
finishRefresh | noMore?: (Object | undefined | null)[] | undefined | null | boolean | void | 结束刷新状态 |
finishLoadMore | noMore?: (Object | undefined | null)[] | undefined | null | boolean | void | 结束加载更多状态 |
showEmpty | visible?: boolean | 控制空页面显示 | |
showHead | visible?: boolean | void | 控制头部布局显示状态 |
showFoot | visible?: boolean | void | 控制底部布局显示状态 |
showRefreshFooter | visible?: boolean | void | 控制加载更多布局显示状态 |
resetStatus | - | void | 重置所有状态到初始值(包含refreshing/loadMore/showEnd等) |
onScrollIndex | start: number, end: number | void | 列表/网格滚动索引变化回调,当滚动到底部时触发加载 |
onScrollEdge | edge: Edge | void | 滚动视图到达边缘回调(Edge.Bottom时触发加载) |
onScrollFrameBegin | offset: number | BaseRefreshOffsetInterface | 滚动偏移量变化回调,用于判定滑动方向 |
BaseRefreshDataSource 类方法
方法名 | 参数 | 返回值 | 说明 |
---|---|---|---|
add1stItem | data: T | void | 在列表头部插入元素 |
addLastItem | data: T | void | 在列表尾部追加元素 |
addItem | index: number, data: T | void | 在指定位置插入元素 |
delete1stItem | - | void | 删除第一个元素 |
deleteItemByIndex | index: number | void | 删除指定索引元素 |
deleteItem | data: T | void | 删除指定元素 |
setItem | index: number, data: T | void | 更新指定位置元素 |
clear | - | void | 清空所有数据 |
notifyDataReload | - | void | 通知数据重载 |
notifyDataAdd | index: number | void | 通知数据添加事件 |
notifyDataChange | index: number | void | 通知数据变更事件 |
notifyDataDelete | index: number | void | 通知数据删除事件 |
complete | data: T[] | undefined | void | 完成加载操作(根据刷新状态决定替换或追加数据) |
作者其他库
- 鸿蒙数据库工具:https://gitee.com/HW-Commons/ZDbUtil
联系我们
欢迎大家提交issue、PR(可以统一收集问题,方便更多人查阅,会第一时间回复处理) ,或进群交流(+v: _hhbin)。
