鸿蒙原生开发-自定义实现refresh组件的下拉样式

一:起因

有群友在提问的时候问到了下拉刷新的样式怎么更改,刚好我又做过了这个功能,然后写一篇文章来总结一下

二:核心原理

在HarmonyOS开发中,实现自定义下拉刷新样式的关键在于使用Refresh组件。该组件支持传入一个自定义的builder,用于定义下拉刷新时的显示内容。通过利用状态变量和构建器方法,可以动态地控制和更新刷新状态的显示内容。

三:思路

  • 定义状态变量

    • refreshIng: 控制下拉刷新状态。
    • refreshStatus: 控制刷新状态文本。
    • loadingfinished: 控制底部加载状态。
  • 创建刷新状态文本生成方法

    • 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和实现步骤。

相关推荐
别说我什么都不会1 分钟前
ohos.net.http请求HttpResponse header中set-ccokie值被转成array类型
网络协议·harmonyos
码是生活20 分钟前
鸿蒙开发排坑:解决 resourceManager.getRawFileContent() 获取文件内容为空问题
前端·harmonyos
鸿蒙场景化示例代码技术工程师25 分钟前
基于Canvas实现选座功能鸿蒙示例代码
华为·harmonyos
小脑斧爱吃鱼鱼1 小时前
鸿蒙项目笔记(1)
笔记·学习·harmonyos
鸿蒙布道师2 小时前
鸿蒙NEXT开发对象工具类(TS)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
zhang1062092 小时前
HarmonyOS 基础组件和基础布局的介绍
harmonyos·基础组件·基础布局
马剑威(威哥爱编程)3 小时前
在HarmonyOS NEXT 开发中,如何指定一个号码,拉起系统拨号页面
华为·harmonyos·arkts
GeniuswongAir4 小时前
Flutter极速接入IM聊天功能并支持鸿蒙
flutter·华为·harmonyos
90后的晨仔7 小时前
鸿蒙ArkUI框架中的状态管理
harmonyos
别说我什么都不会1 天前
OpenHarmony 5.0(API 12)关系型数据库relationalStore 新增本地数据变化监听接口介绍
api·harmonyos