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及自定义组件
  • 加载更多及自定义组件
相关推荐
田野追逐星光9 小时前
STL容器list的模拟实现
开发语言·c++·list
浪客灿心2 天前
list_stack_queue
数据结构·list
HIT_Weston2 天前
121、【Ubuntu】【Hugo】首页板块配置:list 模板(一)
linux·ubuntu·list
苏宸啊3 天前
list底层实现
c++·list
波波0073 天前
每日一题:在 .NET 中遍历集合(如 List<T>、数组、字典)的过程中进行增删改查会不会有影响?可能引发哪些问题?实际开发中应如何避免?
前端·list
以太浮标3 天前
华为eNSP模拟器综合实验之- 前缀列表(IP Prefix-list --匹配和控制路由信息的强大工具)
tcp/ip·华为·智能路由器·list
jiunian_cn4 天前
【Redis】list数据类型相关指令
数据库·redis·list
田野追逐星光5 天前
STL中容器list -- 讲解超详细
开发语言·c++·list
欧阳x天5 天前
STL讲解(七)——list容器的模拟实现
c++·windows·list
f狐0狸x6 天前
【C++修炼之路】C++ list容器基本用法详解
开发语言·c++·list