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及自定义组件
  • 加载更多及自定义组件
相关推荐
Aliano21710 天前
Arrays.asList和 List<String> list = new ArrayList<>();有什么区别
数据结构·list
BillKu11 天前
Vue3 + TypeScript合并两个列表到目标列表,并且进行排序,数组合并、集合合并、列表合并、list合并
vue.js·typescript·list
77tian11 天前
Java Collections工具类:高效集合操作
java·开发语言·windows·microsoft·list
___波子 Pro Max.12 天前
python list去重
python·list
2401_8582861114 天前
CD45.【C++ Dev】STL库的list的使用
开发语言·数据结构·c++·list
点云SLAM14 天前
PyTorch 中Tensor常用数据结构(int, list, numpy array等)互相转换和实战示例
数据结构·人工智能·pytorch·算法·list·numpy·tensor
haokan_Jia15 天前
以list为输入条件,查询数据库表,java中的mapper层和mybatis层应该怎么写?
java·list·mybatis
haokan_Jia15 天前
【java中使用stream处理list数据提取其中的某个字段,并由List<String>转为List<Long>】
java·windows·list
你是橙子那我是谁16 天前
Redis的list的底层原理
数据库·redis·list
kuki<__>17 天前
List的简单模拟实现
数据结构·windows·list