目录

HarmonyOS:使用Refresh组件实现页面下拉刷新上拉加载更多

一、前言

可以进行页面下拉操作并显示刷新动效的容器组件。

说明

  • 该组件从API Version 8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
  • 该组件从API Version 12开始支持与垂直滚动的Swiper和Web的联动。当Swiper设置loop属性为true时,Refresh无法和Swiper产生联动。

二、子组件

支持单个子组件。

从API version 11开始,Refresh子组件会跟随手势下拉而下移。

三、接口

Refresh(value: RefreshOptions)

创建Refresh容器。

参数:

参数名 类型 必填 说明
value RefreshOptions 刷新组件参数。

四、属性

支持通用属性外,还支持以下属性:

refreshOffset12+

refreshOffset(value: number)

设置触发刷新的下拉偏移量,当下拉距离小于该属性设置值时离手不会触发刷新。

参数:

参数名 类型 必填 说明
value number 下拉偏移量,单位vp。 默认值:未设置promptText参数时为64vp,设置了promptText参数时为96vp。 如果取值为0或负数的时候此接口采用默认值。

pullToRefresh12+

pullToRefresh(value: boolean)

设置当下拉距离超过refreshOffset时是否能触发刷新。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名 类型 必填 说明
value boolean 当下拉距离超过refreshOffset时是否能触发刷新。true表示能触发刷新,false表示不能触发刷新。 默认值:true

五、事件

除支持通用事件外,还支持以下事件:

onStateChange

onStateChange(callback: (state: RefreshStatus) => void)

当前刷新状态变更时,触发回调。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数

参数名 类型 必填 说明
state RefreshStatus 刷新状态。

onRefreshing

onRefreshing(callback: () => void)

进入刷新状态时触发回调。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full
onOffsetChange12+

onOffsetChange(callback: Callback)

下拉距离发生变化时触发回调。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数

参数名 类型 必填 说明
callback Callback 下拉距离。 单位:vp

RefreshStatus枚举说明

Refresh刷新状态枚举。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称 说明
Inactive 0 默认未下拉状态。
Drag 1 下拉中
OverDrag 2 下拉中,下拉距离超过刷新距离。
Refresh 3 下拉结束,回弹至刷新距离,进入刷新中状态。
Done 4 刷新结束,返回初始状态(顶部)。

六、示例

6.1 示例(默认刷新样式)

刷新区域使用默认刷新样式。效果图如下

TestRefreshExample1.ets代码

c 复制代码
@Entry
@Component
struct TestRefreshExample1 {
  @State isRefreshing: boolean = false
  @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']

  build() {
    Column() {
      Refresh({ refreshing: $$this.isRefreshing }) {
        List() {
          ForEach(this.arr, (item: string) => {
            ListItem() {
              Text('' + item)
                .width('70%')
                .height(80)
                .fontSize(16)
                .margin(10)
                .textAlign(TextAlign.Center)
                .borderRadius(10)
                .backgroundColor(0xFFFFFF)
            }
          }, (item: string) => item)
        }
        .onScrollIndex((first: number) => {
          console.info(first.toString())
        })
        .width('100%')
        .height('100%')
        .alignListItem(ListItemAlign.Center)
        .scrollBar(BarState.Off)
      }
      .onStateChange((refreshStatus: RefreshStatus) => {
        console.info('Refresh onStatueChange state is ' + refreshStatus)
      })
      .onOffsetChange((value: number) => {
        console.info('Refresh onOffsetChange offset:' + value)
      })
      .onRefreshing(() => {
        setTimeout(() => {
          this.isRefreshing = false
        }, 2000)
        console.log('onRefreshing test')
      })
      .backgroundColor(0x89CFF0)
      .refreshOffset(64)
      .pullToRefresh(true)
    }
  }
}
6.2 示例(设置刷新区域显示文本)

通过promptText参数设置刷新区域显示文本。

TestRefreshExample2.ets代码

c 复制代码
@Entry
@Component
struct TestRefreshExample2 {
  @State isRefreshing: boolean = false
  @State promptText: string = "Refreshing..."
  @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']

  build() {
    Column() {
      Refresh({ refreshing: $$this.isRefreshing, promptText: this.promptText }) {
        List() {
          ForEach(this.arr, (item: string) => {
            ListItem() {
              Text('' + item)
                .width('70%')
                .height(80)
                .fontSize(16)
                .margin(10)
                .textAlign(TextAlign.Center)
                .borderRadius(10)
                .backgroundColor(0xFFFFFF)
            }
          }, (item: string) => item)
        }
        .onScrollIndex((first: number) => {
          console.info(first.toString())
        })
        .width('100%')
        .height('100%')
        .alignListItem(ListItemAlign.Center)
        .scrollBar(BarState.Off)
      }
      .backgroundColor(0x89CFF0)
      .pullToRefresh(true)
      .refreshOffset(96)
      .onStateChange((refreshStatus: RefreshStatus) => {
        console.info('Refresh onStatueChange state is ' + refreshStatus)
      })
      .onOffsetChange((value: number) => {
        console.info('Refresh onOffsetChange offset:' + value)
      })
      .onRefreshing(() => {
        setTimeout(() => {
          this.isRefreshing = false
        }, 2000)
        console.log('onRefreshing test')
      })
    }
  }
}
6.3 示例(自定义刷新区域显示内容-builder)

通过builder参数自定义刷新区域显示内容。

TestRefreshExample3.ets代码

复制代码
@Entry
@Component
struct TestRefreshExample3 {
  @State isRefreshing: boolean = false
  @State arr: string[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']

  @Builder
  customRefreshComponent() {
    Stack() {
      Row() {
        LoadingProgress().height(32)
        Text("Refreshing...").fontSize(16).margin({ left: 20 })
      }
      .alignItems(VerticalAlign.Center)
    }
    .align(Alignment.Center)
    .clip(true)
    // 设置最小高度约束保证自定义组件高度随刷新区域高度变化时自定义组件高度不会低于minHeight
    .constraintSize({ minHeight: 32 })
    .width("100%")
  }

  build() {
    Column() {
      Refresh({ refreshing: $$this.isRefreshing, builder: this.customRefreshComponent() }) {
        List() {
          ForEach(this.arr, (item: string) => {
            ListItem() {
              Text('' + item)
                .width('70%')
                .height(80)
                .fontSize(16)
                .fontColor(Color.Black)
                .textAlign(TextAlign.Center)
                .margin(10)
                .borderRadius(10)
                .backgroundColor(0xFFFFFF)
            }
          }, (item: string) => item)
        }
        .onScrollIndex((start: number, end: number) => {
          console.log(`当前滚动的 index start = ${start} end = ${end}`)
        })
        .alignListItem(ListItemAlign.Center)
        .scrollBar(BarState.Off)
      }
      .backgroundColor(0x89CFF0)
      .pullToRefresh(true) // 设置当下拉距离超过refreshOffset时是否能触发刷新。true表示能触发刷新, 默认值:true
      .refreshOffset(64) // 下拉偏移量,单位vp。默认值:未设置promptText参数时为64vp,设置了promptText参数时为96vp。 如果取值为0或负数的时候此接口采用默认值。
      .onStateChange((refreshStatus: RefreshStatus) => {
        console.log(`当前刷新状态回调 onStatueChange state is  ${refreshStatus}`)
      })
      .onRefreshing(() => {
        setTimeout(() => {
          this.isRefreshing = false;
          console.log("停止刷新")
        }, 2000)
        console.log("onRefreshing 测试")
      })
    }
  }
}
6.4 示例(实现下拉刷新上拉加载更多)

Refresh组件与List组件组合实现下拉刷新上拉加载更多效果。

TestListRefreshLoad.ets代码

复制代码
@Entry
@Component
struct TestListRefreshLoad {
  @State arr: Array<number> = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  @State refreshing: boolean = false;
  @State refreshOffset: number = 0;
  @State refreshState: RefreshStatus = RefreshStatus.Inactive;
  @State isLoading: boolean = false;

  @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)
      }
    }
    .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(this.arr, (item: number) => {
          ListItem() {
            Text('' + item)
              .width('100%')
              .height(80)
              .fontSize(16)
              .textAlign(TextAlign.Center)
              .backgroundColor(0xFFFFFF)
          }.borderWidth(1)
        }, (item: string) => item)

        ListItem() {
          this.footer();
        }
      }
      .onScrollIndex((start: number, end: number) => {
        // 当达到列表末尾时,触发新数据加载
        if (end >= this.arr.length - 1) {
          this.isLoading = true;
          // 模拟新数据加载
          setTimeout(() => {
            for (let i = 0; i < 10; i++) {
              this.arr.push(this.arr.length);
              this.isLoading = false;
            }
          }, 700)
        }
      })
      .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(() => {
      // 模拟数据刷新
      setTimeout(() => {
        this.refreshing = false;
      }, 2000)
    })
  }
}
本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
搞瓶可乐11 小时前
鸿蒙ArkUI实战之组件;Text组件,Image组件,Button组件,Span组件和TextInput组件的使用场景及使用方法
华为·harmonyos·鸿蒙系统·arkui·组件化开发·基础组件使用
九丘教育12 小时前
【仓颉 + 鸿蒙 + AI Agent】CangjieMagic框架(15):NaiveExecutor
人工智能·华为·harmonyos
搞瓶可乐16 小时前
鸿蒙ArkUI实战之TextArea组件、RichEditor组件、RichText组件、Search组件的使用
华为·harmonyos·arkui·搜索框·富文本组件·富文本输入框·鸿蒙原生api
孤寂码农_defector16 小时前
鸿蒙系统的 “成长烦恼“:生态突围与技术迭代的双重挑战
macos·华为·objective-c·cocoa·harmonyos
别说我什么都不会17 小时前
【仓颉三方库】 数据解析——TOML4CJ
harmonyos
鸿蒙布道师17 小时前
鸿蒙NEXT开发LRUCache缓存工具类(单例模式)(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
城中的雾19 小时前
HarmonyOS Next 编译之如何构建不同包名应用
harmonyos·arkts
别说我什么都不会19 小时前
【仓颉三方库】 数据解析—— jwt4cj
harmonyos
周胡杰20 小时前
鸿蒙-跨设备互通,设备互通提供跨设备的相机、扫描、图库访问能力,平板或2in1设备可以调用手机的相机、扫描、图库等功能。
数码相机·华为·自动化·电脑·harmonyos·鸿蒙·鸿蒙系统
SuperHeroWu720 小时前
【HarmonyOS 5】VisionKit人脸活体检测详解
华为·harmonyos·人脸活体检测·visionkit