HarmonyOS开发之(下拉刷新,上拉加载)控件pulltorefresh组件的使用

效果图:

一:下载安装(地址:OpenHarmony-SIG/PullToRefresh

ohpm install @ohos/pulltorefresh

二:使用lazyForEarch的数据作为数据源

export  class  BasicDataSource implements IDataSource{

  private listeners: DataChangeListener[] = []

  public totalCount(): number {
    return 0
  }

  public getData(index: number): Object {
    return index
  }
  // 该方法为框架侧调用,为LazyForEach组件向其数据源处添加listener监听
  registerDataChangeListener(listener: DataChangeListener): void {
    if (this.listeners.indexOf(listener) < 0) {
      console.info('add listener')
      this.listeners.push(listener)
    }
  }
  // 该方法为框架侧调用,为对应的LazyForEach组件在数据源处去除listener监听
  unregisterDataChangeListener(listener: DataChangeListener): void {
    const pos = this.listeners.indexOf(listener);
    if (pos >= 0) {
      console.info('remove listener')
      this.listeners.splice(pos, 1)
    }
  }

  // 通知LazyForEach组件需要重载所有子组件
  notifyDataReload(): void {
    this.listeners.forEach(listener => {
      listener.onDataReloaded()
    })
  }
  // 通知LazyForEach组件需要在index对应索引处添加子组件
  notifyDataAdd(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataAdd(index)
    })
  }
  // 通知LazyForEach组件在index对应索引处数据有变化,需要重建该子组件
  notifyDataChange(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataChange(index)
    })
  }
  // 通知LazyForEach组件需要在index对应索引处删除该子组件
  notifyDataDelete(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataDelete(index)
    })
  }
  // 数据移动起始位置与数据移动目标位置交换完成后调用
  notifyDataMove(from: number, to: number): void {
    this.listeners.forEach(listener => {
      listener.onDataMove(from, to)
    })
  }
}

export  class MyDataNewSource extends BasicDataSource{
  private dataArray:  string[]=[]



  public totalCount(): number {
    return this.dataArray.length
  }

  public getData(index: number): Object {
    return this.dataArray[index]
  }

  public addData(index: number, data: string): void {
    this.dataArray.splice(index, 0, data)
    this.notifyDataAdd(index)
  }

  public pushData(data: string): void {
    this.dataArray.push(data)
    this.notifyDataAdd(this.dataArray.length - 1)// 重新加载
  }

  public clear():void{
    this.dataArray=[]
  }
}

三:快速使用

import router from '@ohos.router';
import { dateList } from '../model/wallpaperBeanList';
import weatherApi from '../DbUtils/WeatherApi';
import { MyDataNewSource} from '../DbUtils/MyDataSource';
import { PullToRefresh, PullToRefreshConfigurator } from '@ohos/pulltorefresh'

@Component
export struct WallpaperPage {
  @State typeID: number = 0
  @State wallpaperUrlList: dateList [] = []
  dataSource: MyDataNewSource = new MyDataNewSource()
  // 需绑定列表或宫格组件
  private scroller: Scroller = new Scroller()
  timer: null | number = null
  private currentPage: number = 1;//当前页码
  private pageSize: number = 12; // 默认加载数量
  private refreshConfigurator: PullToRefreshConfigurator = new PullToRefreshConfigurator();


  aboutToAppear() {
    this.refreshConfigurator
      .setHasRefresh(true)// 是否具有下拉刷新功能
      .setHasLoadMore(true)// 是否具有上拉加载功能
      .setMaxTranslate(150)// 可下拉上拉的最大距离
      .setSensitivity(1)// 下拉上拉灵敏度
      .setListIsPlacement(false)// 滑动结束后列表是否归位
      .setAnimDuration(300)// 滑动结束后,回弹动画执行时间
      .setRefreshHeight(50)// 下拉动画高度
      .setRefreshColor('#638EEF')// 下拉动画颜色
      .setRefreshBackgroundColor($r('app.color.home_bg'))// 下拉动画区域背景色
      .setRefreshTextColor('#638EEF')// 下拉加载完毕后提示文本的字体颜色
      .setRefreshTextSize(15)// 下拉加载完毕后提示文本的字体大小
      .setRefreshAnimDuration(1000)// 下拉动画执行一次的时间
      .setLoadImgHeight(50)// 上拉图片高度
      .setLoadBackgroundColor($r('app.color.home_bg'))// 上拉动画区域背景色
      .setLoadTextColor('#638EEF')// 上拉文本的字体颜色
      .setLoadTextSize(15)// 上拉文本的字体大小
      .setLoadTextPullUp1('请继续上拉...')// 上拉1阶段文本
      .setLoadTextPullUp2('释放即可刷新')// 上拉2阶段文本
      .setLoadTextLoading('加载中...') // 上拉加载更多中时的文本
     // .setRefreshCompleteTextHoldTime(500) //上拉刷新后停留的时间, 默认一秒, 建议设置500
    this.fetchWallpapers(this.currentPage)
  }

  //根据当前页面查找数据源(typeID=>类型id)
  private fetchWallpapers(pageNum: number = 1) {
    weatherApi.wallpaperList(this.typeID, pageNum, this.pageSize).then(wallpaperListBean => {
      this.wallpaperUrlList = wallpaperListBean.data.list // Assuming your API structure
      this.dataSource.clear() // Clear the old data
      for (let index = 0; index < this.wallpaperUrlList.length; index++) {
        this.dataSource.pushData(this.wallpaperUrlList[index].imgUrl)
      }
    }).catch(error => {
      console.error("Error fetching wallpapers:", error)
    })
  }

  build() {
    Column() {
      PullToRefresh({
        // 必传项,需绑定传入主体布局内的列表或宫格组件
        scroller: this.scroller,
        // 必传项,自定义主体布局,内部有列表或宫格组件
        customList: () => {
          // 一个用@Builder修饰过的UI方法
          this.getListView()
        },
        refreshConfigurator:this.refreshConfigurator,
        mWidth:'100%',
        mHeight:'100%',
        // 可选项,下拉刷新回调
        onRefresh: () => {
          return new Promise<string>((resolve, reject) => {
            // 网络请求操作,请求网络2秒后得到数据,通知组件,变更列表数据
            this.fetchWallpapers(1) // Fetch first page data
            this.currentPage = 1 // Reset the page count
            this.timer = setTimeout(() => {
              resolve('刷新成功')
              console.log(' 刷新成功')
            }, 2000)
          })
        },
        // 可选项,上拉加载更多回调
        onLoadMore: () => {
          return new Promise<string>((resolve, reject) => {
            // 网络请求操作,请求网络2秒后得到数据,通知组件,变更列表数据
            this.currentPage++; // Increment the page number
            this.fetchWallpapers(this.currentPage); // Fetch the next page of data
            this.timer = setTimeout(() => {
              resolve('上拉加载完成')
              console.log('上拉加载完成')
            }, 2000)
          })
        },
        customLoad: null,
        customRefresh: null,
      })
    }
    .width('100%')
    .height('100%')

  }

  @Builder
  private getListView() {
    Grid(this.scroller) {
      LazyForEach(this.dataSource, (item, index) => {
        GridItem() {
          // 显示网络图片
          Image(item || $r('app.color.color_white_f0f8'))
            .width('100%')
            .height('20%')
            .alt($r('app.color.color_white_f0f8'))
            .borderRadius(8)
            .onAppear(() => { //组件挂载显示触发
              if (index) {
                console.log("Loading  onAppear: index=" + item + ' content= ' + this.dataSource.getData(index));
              }
            })
            .onDisAppear(() => { //组件卸载载显示触发
              if (index) {
                console.log("Loading  onDisAppear: index=" + index + ' content= ' + this.dataSource.getData(index));
              }
            })
            .onClick(() => this.handleImageClick(item)); // 注册点击事件
        }

      }, (item: string) => item)
    }
    .columnsTemplate('1fr 1fr 1fr')
    .columnsGap(15)
    .rowsGap(10)
    .cachedCount(10)
    .margin({top:15})
    .layoutDirection(GridDirection.Row)
    .width('90%')
    .height('100%')
  }

  aboutToDisappear() {
    clearTimeout(this.timer)
    this.dataSource.clear()
  }

  // 处理点击事件
  handleImageClick(imageUrl: string) {

    router.pushUrl({
      url: "pages/WallpaperDetailsPage",
      params: {
        imageUrl: imageUrl
      }
    })
  }
}

注意:在api9 开发的时候注意以下两点

1,依赖PullToRefresh 中

复制代码
@Link data: Object[] 改==》 @State data: Object[]=[];

不然使用的时候PullToRefresh 会报:'@Link' decorated 'data' must be initialized through the component constructor. <ArkTSCheck>

2,同样的在PullToRefresh中找到 this.scroller.isAtEnd(),注释掉,api9 中找不到 this.scroller.isAtEnd()方法

复制代码
相关推荐
枫叶丹43 小时前
【HarmonyOS之旅】HarmonyOS开发基础知识(三)
华为od·华为·华为云·harmonyos
SoraLuna8 小时前
「Mac畅玩鸿蒙与硬件47」UI互动应用篇24 - 虚拟音乐控制台
开发语言·macos·ui·华为·harmonyos
AORO_BEIDOU11 小时前
单北斗+鸿蒙系统+国产芯片,遨游防爆手机自主可控“三保险”
华为·智能手机·harmonyos
博览鸿蒙13 小时前
鸿蒙操作系统(HarmonyOS)的应用开发入门
华为·harmonyos
Damon小智20 小时前
HarmonyOS NEXT 技术实践-基于基础视觉服务的多目标识别
华为·harmonyos
匹马夕阳1 天前
华为笔记本之糟糕的体验
华为·笔记本电脑
egekm_sefg1 天前
华为、华三交换机纯Web下如何创关键VLANIF、操作STP参数
网络·华为
岳不谢2 天前
华为DHCP高级配置学习笔记
网络·笔记·网络协议·学习·华为
爱笑的眼睛112 天前
uniapp 极速上手鸿蒙开发
华为·uni-app·harmonyos
K.P2 天前
鸿蒙元服务从0到上架【第三篇】(第二招有捷径)
华为·harmonyos·鸿蒙系统