参考网址:Refresh-滚动与滑动-ArkTS组件-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者
1.数据基类
//根据自己的业务数据扩展此类
//注意:一定要继承Object
export class PullToRefreshBean extends Object{
name: string = ''
num: number = 0
//一定要写构造,不然取不到数据
constructor(name: string, num: number) {
super()
this.name = name
this.num = num
}
}
2.PullToRefreshListener监听器
export interface PullToRefreshListener{
loadMore: () => void;//监听加载更多
refresh: () => void//监听数据刷新
//错误写法:(这种写法应该是把方法当成了属性来实现)
//loadMore(): void;
//refresh(): void;
}
3.PullToRefreshView刷新组件(相当于Android中自定义控件)
import { PullToRefreshListener } from "../ViewModel/PullToRefreshListener";
@Component
export struct PullToRefreshView{
@Link arr: Array<Object>
@Link refreshing: boolean
@State refreshOffset: number = 0;
@State refreshState: RefreshStatus = RefreshStatus.Inactive;
@State canLoad: boolean = false;
@Link isLoading: boolean
@Prop listener: PullToRefreshListener
@Builder listItem(item: Object) {}
@BuilderParam item: (item: Object) => void = this.listItem
//头部刷新
@Builder
refreshBuilder() {
Stack({ alignContent: Alignment.Bottom }) {
// 可以通过刷新状态控制是否存在Progress组件
// 当刷新状态处于下拉中或刷新中状态时Progress组件才存在
if (this.refreshState != RefreshStatus.Inactive && this.refreshState != RefreshStatus.Done) {
//转圈加载
// Progress({ value: this.refreshOffset, total: 64, type: ProgressType.Ring })
// .width(32).height(32)
// .style({ status: this.refreshing ? ProgressStatus.LOADING : ProgressStatus.PROGRESSING })
// .margin(10)
Row() {
LoadingProgress().height(32).width(48)
Text("正在刷新...")
}.width("100%")
.height(64)
.justifyContent(FlexAlign.Center)
}
}
.clip(true)
.height("100%")
.width("100%")
}
//底部加载
@Builder
footer() {
Row() {
LoadingProgress().height(32).width(48)
Text("加载中...")
}.width("100%")
.height(64)
.justifyContent(FlexAlign.Center)
// 当不处于加载中状态时隐藏组件
.visibility(this.isLoading ? Visibility.Visible : Visibility.Hidden)
}
build() {
Refresh({ refreshing: $$this.refreshing, builder: this.refreshBuilder() }) {
List() {
//ForEach中不加index: number,会出只显示一条数据
ForEach(this.arr, (item: Object, index: number) => {
this.item(item)
}, (item: Object, index: number) => index.toString())
ListItem() {
this.footer();
}
}
.onScrollIndex((start: number, end: number) => {
// 当达到列表末尾时,触发新数据加载
if (this.canLoad && end >= this.arr.length - 1) {
this.canLoad = false;
this.isLoading = true;
// 数据加载监听
this.listener.loadMore()
}
})
.onScrollFrameBegin((offset: number, state: ScrollState) => {
// 只有当向上滑动时触发新数据加载
if (offset > 5 && !this.isLoading) {
this.canLoad = true;
}
return { offsetRemain: offset };
})
.scrollBar(BarState.Off)
// 开启边缘滑动效果
.edgeEffect(EdgeEffect.Spring, { alwaysEnabled: true })
}
.width('100%')
.height('100%')
.backgroundColor(0xDCDCDC)
.onOffsetChange((offset: number) => {
this.refreshOffset = offset;
})
.onStateChange((state: RefreshStatus) => {
this.refreshState = state;
})
.onRefreshing(() => {
//刷新监听
this.listener.refresh()
})
}
}
4.组件中使用
import {PullToRefreshView } from "./PullToRefreshView";
import { PullToRefreshListener } from "../ViewModel/PullToRefreshListener";
import { PullToRefreshBean } from "../constants/PullToRefreshBean";
@Entry({routeName: 'IndexPage'})
@Component
export struct IndexPage{
@State arr: Array<PullToRefreshBean> = [];
@State refreshing: boolean = false;
@State isLoading: boolean = false;
//生命周期方法,在build方法之前
aboutToAppear(): void {
//console.log(`上一个界面传过来的参数:${(router.getParams() as ParamsBean).name}`)
//接口调数据(此处是测试数据)
for (let index = 0; index < 10; index++) {
this.arr.push(new PullToRefreshBean(`${index}`, index))
}
}
@Builder
listItem(item: Object) {
ListItem() {
//列表条目组件布局,根据业务需求自己扩展,此处也可以提取到子组件中(为了代码简洁和解耦)
Text('' + (item as PullToRefreshBean).name)
.width('100%')
.height(80)
.fontSize(16)
.textAlign(TextAlign.Center)
.backgroundColor(0xFFFFFF)
}.borderWidth(1)
.onClick(() => {
//列表条目点击事件监听
console.log('我点击的条目是:'+item)
})
}
@State listener: PullToRefreshListener = {
loadMore: (): void => {
console.log('加载数据')
setTimeout(() => {
let a = this.arr.length-1
for (let index = a; index < a+10; index++) {
this.arr.push(new PullToRefreshBean(`${index}`, index))
}
this.isLoading = false;
}, 2000)
},
refresh: (): void => {
console.log('刷新数据');
setTimeout(() => {
this.refreshing = false;
}, 2000)
}
}
build() {
Column(){
PullToRefreshView({
arr: this.arr,
item: this.listItem,
listener: this.listener,
refreshing: this.refreshing,
isLoading: this.isLoading
})
}
}
}
说明:我是根据官网提供的Refresh实例代码封装的简单使用(代码可直接使用),各位大神有其他酷炫的效果可以交流交流!!!