一:起因
有群友在提问的时候问到了下拉刷新的样式怎么更改,刚好我又做过了这个功能,然后写一篇文章来总结一下
二:核心原理
在HarmonyOS开发中,实现自定义下拉刷新样式的关键在于使用Refresh
组件。该组件支持传入一个自定义的builder
,用于定义下拉刷新时的显示内容。通过利用状态变量和构建器方法,可以动态地控制和更新刷新状态的显示内容。
三:思路
-
定义状态变量:
refreshIng
: 控制下拉刷新状态。refreshStatus
: 控制刷新状态文本。loading
和finished
: 控制底部加载状态。
-
创建刷新状态文本生成方法:
getStatusText()
: 根据不同的刷新状态返回相应的文本,如"继续下拉"、"松手加载"、"加载中"等。
-
创建自定义刷新显示内容的构建器方法:
getRefreshDisPlay()
: 使用Row
布局,包含进度条和状态文本,根据当前的刷新状态动态更新显示内容。
-
实现主构建方法:
- 使用
Refresh
组件,传入refreshing
状态和builder
方法。 - 使用
List
组件渲染数据项和底部加载内容。 - 处理
onReachEnd
事件,实现上拉加载功能。 - 处理
onStateChange
事件,实现下拉刷新功能,更新刷新状态和显示内容。
- 使用
四:核心api
-
Refresh
组件:- 用于实现下拉刷新功能,支持传入
refreshing
状态和自定义的builder
方法。 refreshing
: 控制刷新状态。builder
: 自定义刷新时的显示内容。
- 用于实现下拉刷新功能,支持传入
-
LoadingProgress
组件:- 显示加载进度条。
color
,width
,height
: 设置进度条的颜色和尺寸。
-
Text
组件:- 显示文本内容。
fontColor
,fontSize
: 设置文本的颜色和字体大小。
-
@Builder getRefreshDisPlay()
: 这是一个构建器函数,用来生成自定义的刷新显示内容。- 使用
Row
布局,设置间距为10。 - 显示加载进度条,并设置颜色和尺寸。
- 显示由
getStatusText
函数返回的刷新状态文本。
- 使用
-
@Builder getRefreshDisPlay()
: 这是一个构建器函数,用来生成自定义的刷新显示内容。- 使用
Row
布局,设置间距为10。 - 显示加载进度条,并设置颜色和尺寸。
- 显示由
getStatusText
函数返回的刷新状态文本。
- 使用
五:代码举例(关键地方都给了注释)
less
@Component
struct HmList {
@State
refreshIng: boolean = false // 控制下拉刷新的变量
// 传入数据的数组 根据数组进行渲染
@Prop
dataSource: object[] = [] // 数据源
// 上拉加载的方法
onLoad: () => void = () => {
} // 由调用者传入
// 下拉刷新方法
onRefresh: () => void = () => {
} // 下拉刷新的方法
// 需要一个标记 还没有数据的标记
@Prop
finished: boolean = false // 是否还有下一页数据
@State
loading: boolean = false // 是否正在加载中 1.显示加载中文本 2. 用来做阀门 当前这次请求没结束之前 下次请求滚远点
loadingText: string = "加载中.." // 加载中的文本
finishText: string = "没有数据啦" // 所有数据加载完成的文本
@BuilderParam
renderItem: (item: object) => void // 由调用者传入 由HmList调用 传入每一个项的数据
@State
refreshStatus: RefreshStatus = RefreshStatus.Inactive
@Builder
getBottomDisplay() {
// 获取底部的展示内容
Row({ space: 10 }) {
if (this.finished) {
// 此时应该没有动画的loading
Text(this.finishText)
.fontSize(14)
.fontColor($r('app.color.text_secondary'))
} else {
Text(this.loadingText)
.fontSize(14)
.fontColor($r('app.color.text_secondary'))
LoadingProgress()
.width(20)
.aspectRatio(1)
.color($r('app.color.text_secondary'))
}
}
.width('100%')
.height(50)
.justifyContent(FlexAlign.Center)
}
// 动态生产文本
getStatusText() {
switch (this.refreshStatus) {
case RefreshStatus.Inactive:
return ''
case RefreshStatus.Drag:
return '继续下拉'
case RefreshStatus.OverDrag:
return '松手加载'
case RefreshStatus.Refresh:
return '加载中'
}
return ''
}
@Builder
getRefreshDisPlay() {
Row({ space: 10 }) {
LoadingProgress()
.color($r('app.color.primary'))
.width(40)
.height(40)
Text(this.getStatusText())
.fontColor($r('app.color.text_secondary'))
.fontSize(14)
}
.justifyContent(FlexAlign.Center)
.height(50)
.width("100%")
}
build() {
// Refresh组件支持传入一个自定义的builder来定义刷新时的显示内容
Refresh({ refreshing: $$this.refreshIng ,builder :this.getRefreshDisPlay()}) {
List() {
ForEach(this.dataSource, (item: object) => {
// 每一项的结构的UI内容不是由列表决定 而由使用者决定
// 传入builderParam if确保 renderItem 是一个有效的函数。
if (this.renderItem) {
this.renderItem(item)
}
})
// 最后放置文本的地方
ListItem() {
this.getBottomDisplay()
}
}
.onReachEnd(async () => {
// 实现上拉加载
// 需要一个标记 是否已经加载完所有数据
// 在没有加载完所有页数据的情况 且没有请求在进程中的情况下
if (!this.finished && !this.loading) {
this.loading = true // 关闭阀门
await this.onLoad() //实现上拉加载
this.loading = false // 打开阀门
}
})
}
.onStateChange(async (State) => {
// 实现下拉刷新
this.refreshStatus = State
if (State === RefreshStatus.Refresh) {
// 松手加载
await this.onRefresh() // 调用刷新方法
this.refreshIng = false // 关闭下拉的动画效果
this.loading = false // 关闭上拉刷新的loading
// 下拉刷新意味着所有数据全都不要 重新来过
}
})
}
}
export { HmList }
六 : 效果图
七:总结
关键在于利用Refresh
组件和其builder
属性,自定义刷新时的显示内容。同时,结合状态变量和构建器方法,可以动态更新刷新状态,显示不同的提示文本和加载动画。希望通过这个总结,能帮助你更好地理解和应用这些核心API和实现步骤。