HarmonyOS NEXT星河版之自定义List下拉刷新与加载更多

文章目录

一、加载更多

借助ListonReachEnd方法,实现加载更多功能,效果如下:

ts 复制代码
@Component
export struct HPList {
  // 数据源
  @Prop dataSource: object[] = []
  // 加载更多是否ing
  @State isLoadingMore: boolean = false
  // 是否还有更多
  @Prop hasMore: boolean = false
  // 渲染Item
  @BuilderParam renderItem: (item: object) => void
  // 加载更多回调
  onLoadMore: () => void = () => {
  }
  // 加载更多文案
  loadingMoreText: string = '加载中...'
  // 没有更多文案
  noMoreDataText: string = '没有更多啦'

  @Builder
  getLoadMoreView() {
    Row() {
      if (!this.hasMore) {
        Text(this.noMoreDataText)
          .fontSize(14)
          .fontColor($r('app.color.text_secondary'))
      } else {
        Row({ space: 8 }) {
          LoadingProgress()
            .width(30)
            .height(30)
            .color(Color.Orange)
          Text(this.loadingMoreText)
            .fontSize(14)
            .fontColor($r('app.color.text_secondary'))
        }
      }
    }
    .height(60)
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }

  build() {
    List() {
      ForEach(this.dataSource, (item: object) => {
        ListItem() {
          if (this.renderItem) {
            this.renderItem(item)
          }
        }
      })
      // 加载更多view
      ListItem() {
        this.getLoadMoreView()
      }
    }
    .onReachEnd(async () => {
      if (!this.isLoadingMore && this.hasMore) {
        this.isLoadingMore = true
        await this.onLoadMore()
        this.isLoadingMore = false
      }
    })
  }
}

使用:

ts 复制代码
import { HPList } from '@hp/basic'
import { promptAction } from '@kit.ArkUI'

@Preview
@Component
export struct Task {
  // 模拟数据
  @State dataList: Person[] = [{
    name: '1'
  }, {
    name: '2'
  }, {
    name: '3'
  }, {
    name: '4'
  }, {
    name: '5'
  }, {
    name: '6'
  }, {
    name: '7'
  }, {
    name: '8'
  }, {
    name: '9'
  }, {
    name: '10'
  }, {
    name: '11'
  }, {
    name: '12'
  }]
  @State hasMore: boolean = true
  isFirstIn: boolean = true

  @Builder
  renderItem(item: object) {
    Row() {
      Text(JSON.stringify(item))
        .fontSize(16)
        .textAlign(TextAlign.Center)
    }
    .width('100%')
    .height(80)
    .borderRadius(15)
    .backgroundColor(Color.Pink)
    .justifyContent(FlexAlign.Center)
    .margin({ bottom: 10 })
  }

  /**
   * 加载更多
   */
  async loadMore() {
    // 首次渲染数据为空时,也会调loadMore
    if (this.isFirstIn) {
      this.isFirstIn = false
      return
    }
    await new Promise<void>((resolve, reject) => {
      setTimeout(() => {
        // 模拟数据
        this.dataList = this.dataList.concat(this.dataList.slice(5))
        if (this.dataList.length > 30) {
          this.hasMore = false
        }
        resolve()
      }, 3000)
    });
  }

  build() {
    HPList({
      dataSource: this.dataList,
      hasMore: this.hasMore,
      renderItem: (item: object) => {
        this.renderItem(item)
      },
      onLoadMore: () => {
        this.loadMore()
      }
    })
  }
}

class Person {
  name: string = ''
}

二、下拉刷新

通过Refresh实现下拉刷新,并自定义头部,效果如下:


代码如下:

ts 复制代码
import { promptAction } from '@kit.ArkUI'

@Component
export struct HPList {
  // 数据源
  @Prop dataSource: object[] = []
  // 加载更多是否ing
  @State isLoadingMore: boolean = false
  // 是否还有更多
  @Prop hasMore: boolean = false
  // 渲染Item
  @BuilderParam renderItem: (item: object) => void
  // 加载更多回调
  onLoadMore: () => void = () => {
  }
  // 加载更多文案
  loadingMoreText: string = '加载中...'
  // 没有更多文案
  noMoreDataText: string = '没有更多啦'
  // 是否下拉刷新ing
  @State isRefreshing: boolean = false
  // 下拉刷新回调
  onRefresh: () => void = () => {
  }
  @State refreshState: RefreshStatus = RefreshStatus.Inactive

  // 获取下拉文本
  getStatusText() {
    switch (this.refreshState) {
      case RefreshStatus.Inactive:
        return ""
      case RefreshStatus.Drag:
        return "继续下拉"
      case RefreshStatus.OverDrag:
        return "松开刷新"
      case RefreshStatus.Refresh:
        return "加载中"
    }
    return ""
  }

  @Builder
  getRefreshView() {
    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%')
  }

  @Builder
  getLoadMoreView() {
    Row() {
      if (!this.hasMore) {
        Text(this.noMoreDataText)
          .fontSize(14)
          .fontColor($r('app.color.text_secondary'))
      } else {
        Row({ space: 8 }) {
          LoadingProgress()
            .width(30)
            .height(30)
            .color(Color.Orange)
          Text(this.loadingMoreText)
            .fontSize(14)
            .fontColor($r('app.color.text_secondary'))
        }
      }
    }
    .height(60)
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }

  build() {
    Refresh({ refreshing: $$this.isRefreshing, builder: this.getRefreshView() }) {
      List() {
        ForEach(this.dataSource, (item: object) => {
          ListItem() {
            if (this.renderItem) {
              this.renderItem(item)
            }
          }
        })
        // 加载更多view
        ListItem() {
          this.getLoadMoreView()
        }
      }
      .onReachEnd(async () => {
        if (!this.isLoadingMore && this.hasMore) {
          this.isLoadingMore = true
          await this.onLoadMore()
          this.isLoadingMore = false
        }
      })
    }
    .onStateChange(async (state) => {
      this.refreshState = state
      if (state === RefreshStatus.Refresh) {
        await this.onRefresh()
        this.isRefreshing = false
      }
    })

  }
}

使用:

ts 复制代码
import { HPList } from '@hp/basic'
import { promptAction } from '@kit.ArkUI'

@Preview
@Component
export struct Task {
  // 模拟数据
  @State dataList: Person[] = [{
    name: '1'
  }, {
    name: '2'
  }, {
    name: '3'
  }, {
    name: '4'
  }, {
    name: '5'
  }, {
    name: '6'
  }, {
    name: '7'
  }, {
    name: '8'
  }, {
    name: '9'
  }, {
    name: '10'
  }, {
    name: '11'
  }, {
    name: '12'
  }]
  @State hasMore: boolean = true
  isFirstIn: boolean = true

  @Builder
  renderItem(item: object) {
    Row() {
      Text(JSON.stringify(item))
        .fontSize(16)
        .textAlign(TextAlign.Center)
    }
    .width('100%')
    .height(80)
    .borderRadius(15)
    .backgroundColor(Color.Pink)
    .justifyContent(FlexAlign.Center)
    .margin({ bottom: 10 })
  }

  async onRefresh() {
    await new Promise<void>((resolve, reject) => {
      setTimeout(() => {
        this.dataList = [{
          name: '旺财'
        },
          {
            name: '张三'
          }, {
            name: '李四'
          }, {
            name: '王五'
          },
          {
            name: '张三1'
          }, {
            name: '李四1'
          }, {
            name: '王五1'
          },
          {
            name: '张三2'
          }, {
            name: '李四2'
          }, {
            name: '王五2'
          }]
        resolve()
      }, 3000)
    });
  }

  /**
   * 加载更多
   */
  async loadMore() {
    // 首次渲染数据为空时,也会调loadMore
    if (this.isFirstIn) {
      this.isFirstIn = false
      return
    }
    promptAction.showToast({ message: 'opppp' })
    await new Promise<void>((resolve, reject) => {
      setTimeout(() => {
        // 模拟数据
        this.dataList = this.dataList.concat(this.dataList.slice(5))
        if (this.dataList.length > 30) {
          this.hasMore = false
        }
        resolve()
      }, 3000)
    });
  }

  build() {
    HPList({
      dataSource: this.dataList,
      hasMore: this.hasMore,
      renderItem: (item: object) => {
        this.renderItem(item)
      },
      onLoadMore:async  () => {
        await this.loadMore()
      },
      onRefresh: async () => {
        await this.onRefresh()
      }
    })
  }
}

class Person {
  name: string = ''
}

三、小结

  • 下拉刷新Refresh及自定义组件
  • 加载更多及自定义组件
相关推荐
熬夜学编程的小王3 小时前
【C++篇】深度解析 C++ List 容器:底层设计与实现揭秘
开发语言·数据结构·c++·stl·list
努力进修8 小时前
“探索Java List的无限可能:从基础到高级应用“
java·开发语言·list
‘’林花谢了春红‘’15 小时前
C++ list (链表)容器
c++·链表·list
阿龟在奔跑18 小时前
引用类型的局部变量线程安全问题分析——以多线程对方法局部变量List类型对象实例的add、remove操作为例
java·jvm·安全·list
ashane131420 小时前
Java list
java·windows·list
djk888821 小时前
.net将List<实体1>的数据转到List<实体2>
数据结构·list·.net
黎明晓月1 天前
PostgreSQL提取JSON格式的数据(包含提取list指定索引数据)
postgresql·json·list
熬夜学编程的小王1 天前
【C++篇】从基础到进阶:全面掌握C++ List容器的使用
开发语言·c++·list·双向链表·迭代器失效
@小博的博客2 天前
C++初阶学习第十一弹——list的用法和模拟实现
开发语言·c++·学习·list
努力学习的小廉3 天前
【list的模拟实现】—— 我与C++的模拟实现(十四)
c++·list