鸿蒙原生开发-自定义实现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和实现步骤。

相关推荐
sanzk4 小时前
华为鸿蒙应用开发
华为·harmonyos
SoraLuna8 小时前
「Mac畅玩鸿蒙与硬件28」UI互动应用篇5 - 滑动选择器实现
macos·ui·harmonyos
ClkLog-开源埋点用户分析9 小时前
ClkLog企业版(CDP)预售开启,更有鸿蒙SDK前来助力
华为·开源·开源软件·harmonyos
mg6689 小时前
鸿蒙系统的优势 开发 环境搭建 开发小示例
华为·harmonyos
lqj_本人10 小时前
鸿蒙next选择 Flutter 开发跨平台应用的原因
flutter·华为·harmonyos
lqj_本人10 小时前
使用 Flutter 绘制一个棋盘
harmonyos
lqj_本人13 小时前
Flutter&鸿蒙next 状态管理框架对比分析
flutter·华为·harmonyos
青瓷看世界14 小时前
华为HarmonyOS打造开放、合规的广告生态 - 插屏广告
华为·harmonyos·广告投放
青瓷看世界14 小时前
华为HarmonyOS借助AR引擎帮助应用实现虚拟与现实交互的能力2-管理AR会话
华为·ar·harmonyos·虚拟现实
2301_7955586415 小时前
鸿蒙的进化史
华为·harmonyos