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

news2024/9/20 1:10:30

效果图:

一:下载安装(地址: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()方法


                

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2125412.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一种简易CAN数据分析器的实现(一)【工程创建+CAN波特率计算工具】

程序实现详见《一种简易CAN数据分析器的实现&#xff08;二&#xff09;【程序实现】》 微信公众号关注&#xff1a;掌芯元器&#xff0c;免费为大家提供嵌入式相关的技术咨询&#xff01;&#xff01;&#xff01; 目录 一、功能需求及实现 1、功能设计及实现 2、软硬件需求…

视频怎么转换成mp3格式?分享5种便捷的转换方法

在日常生活中&#xff0c;我们经常会遇到需要将视频文件中的音频提取出来&#xff0c;转换成MP3格式的情况&#xff0c;以便在手机、MP3播放器或其他设备上播放。今天&#xff0c;我将为大家介绍5种视频转MP3的方法&#xff0c;非常简单便捷&#xff0c;一起来学习下吧。 方法一…

oelove奥壹婚恋征婚相亲交友系统v10.0原生小程序源码(无编译加密)上架经验让你少走弯路

首先大家要明白什么是原生小程序&#xff01;以微信小程序为例&#xff0c;原生小程序就是指在微信指定的平台“开发者工具”按照平台规则开发出来的小程序才是原生小程序&#xff0c;像uniapp它就不属于原生小程序是第三方&#xff0c;原生小程序的好处那一万字也说不完&#…

JavaScript第五天(函数,this,严格模式,高阶函数,闭包,递归,正则,ES6)高级

这里写目录标题 JavaScript高级第03天1.函数的定义和调用1.1函数的定义方式1.2函数的调用 2.this2.1函数内部的this指向2.2改变函数内部 this 指向2.2.1 call方法2.2.2 apply方法2.2.3 bind方法2.2.4 call、apply、bind三者的异同 3.严格模式3.1什么是严格模式3.2开启严格模式3…

21. Revit API: 几何对象(二)- Curve

上篇讲了Revit几何对象的类层次结构&#xff0c;讲了几何元素和几何实例&#xff0c;简单提到了Solid。 这一篇呢&#xff0c;就从构成Solid的边讲起。 一、Edge&#xff08;边&#xff09; Edge在Revit中就是用来表示边的&#xff0c;并且在各种表示几何结构的类中串门。 前…

使用 Elementary 实现开源数据可观测性 — 从零到精通(第一部分)

欢迎来到雲闪世界。我希望在我还是初学者时能有一份循序渐进的实践指南 数据可观测性及其重要性经常被讨论和撰写为现代数据和分析工程的一个重要方面。市场上有许多工具&#xff0c;具有各种功能和价格。在这篇由两部分组成的文章中&#xff0c;我们将重点介绍 Elementary 的…

(k8s)kubernetes 挂载 minio csi 的方式

一、安装Minio&#xff08;Minio分布式集群搭建部署_minio集群最少几台-CSDN博客&#xff09; 生成accessKeyID和secretAccessKey&#xff1a; 二、安装csi-s3插件(在k8s集群上) 首先我们把插件的yaml文件都下载下来&#xff0c;为了保证版本测试的一致性&#xff0c;我们下载…

论文阅读:RGBD GS-ICP SLAM

目录 概要 Motivation 整体框架流程 技术细节 小结 论文地址&#xff1a;[2403.12550] RGBD GS-ICP SLAM (arxiv.org) 代码地址&#xff1a;https://github.com/Lab-of-AI-and-Robotics/GS-ICP-SLAM 概要 RGBD GS-ICP SLAM 是一种结合通用迭代最近点算法&#xff08;Ge…

【基础算法总结】前缀和

目录 一&#xff0c;前缀和算法介绍二&#xff0c;算法原理和代码实现【模板】前缀和【模板】二维前缀和724.寻找数组的中心下标238.除自身以外数组的乘积560.和为k的子数组974.和可被k整除的子数组525.连续数组1314.矩阵区域和 三&#xff0c;算法总结 一&#xff0c;前缀和算…

可能一拆为二,英特尔为何走到今天这一步?

【科技明说 &#xff5c; 科技热点关注】 近来看到外媒消息说&#xff0c;英特尔迫于经营压力&#xff0c;也不得不铤而走险&#xff0c;欲将英特尔一分为二&#xff0c;即芯片制造与芯片设计分离开&#xff0c;互相剥离&#xff0c;独立发展。 于是乎&#xff0c;英特尔将分拆…

图卷积神经网络GNN(一)

图卷积神经网络GNN 研究学习的背景 对于图神经网络&#xff08;GNN&#xff09;来输入的数据是图。&#xff08;解决输入数据不规则情况&#xff09;输入的格式不是固定的 研究涵盖&#xff1a;节点分类&#xff08;nodeclassification&#xff09;、边预测&#xff08;link…

​ArcGIS Pro和ArcGIS的10大区别

本文来源&#xff1a;水经注GIS公众号 如果你经常使用ArcGIS 进行制图和分析&#xff0c;那么你一定听说过ArcGIS Pro&#xff0c;这款软件是Esri未来主打的一款桌面GIS软件&#xff0c;那么这款软件和ArcGIS相比有什么不同呢&#xff0c;这里为你列举了两款软件的10大区别&am…

海康威视相机在QTcreate上的环境配置教程(qt+opencv+海康SDK)

环境配置教程 前言&#xff1a;环境配置&#xff1a;1.海康SDK2.opencv 参考导入文件 前言&#xff1a; 配置环境是编程的第一步&#xff0c;所以写这篇文章来指导环境的配置。如果已经配置好了&#xff0c;想在qt上使用海康的摄像头&#xff0c;可以参考这篇文章&#xff1a;…

骨传导耳机哪个品牌好用?良心测评推荐5大高分骨传导耳机!

在快节奏、数字化的生活时代&#xff0c;耳机成为连接外界与个人世界的桥梁&#xff0c;尤其在户外运动和健身场景中更是不可或缺。传统入耳式耳机虽然携带方便、音质优秀&#xff0c;但长时间佩戴会对耳道和鼓膜造成压力&#xff0c;甚至引发耳部不适。为解决这一痛点&#xf…

windows下自启springboot项目(jar+nginx)

1、将springboot项目打包为jar 2、新建文本文档 test.txt&#xff0c;并输入 java -jar D:\test\test.jar&#xff08;修改为自己的jar包位置&#xff09; 保存 然后修将后缀名改为 .bat 3、在同一目录再新建 文本文档test.txt&#xff0c;输入以下内容&#xff0c;&…

Meme“淘金”热潮下:Meme发射平台的安全风险分析

2023年&#xff0c;Meme赛道成为加密市场和各大公链生态的重点关注板块之一&#xff0c;尤其是在Solana等公链上&#xff0c;Meme代币迎来了爆发。许多Meme代币的交易量飙升&#xff0c;年初Solana生态中的Meme代币交易额甚至达到百亿美元。乘着Meme代币的东风&#xff0c;Meme…

VSCode配置 C/C++ 开发环境

目录 1.概述 2. 安装 C/C 扩展 3. 安装编译器 3.1.Windows 3.2.macOS 3.3.Linux 4. 配置 VSCode 5. 构建和运行 1.概述 在 Visual Studio Code (VSCode) 中配置 C/C 开发环境&#xff0c;需要安装一些扩展和正确配置编译器。以下是详细的步骤&#xff1a; 2. 安装 C/C…

Agilent MSO7104A安捷伦示波器1G 4通道

Agilent MSO7104A安捷伦示波器1G 4通道 附加功能&#xff1a; 带宽&#xff1a;1 GHz 通道&#xff1a;4 个模拟和 16 个数字 采样率&#xff1a;4 GSa/s 记录长度&#xff1a;标准 8 Mpts MegaZoom III 深存储器 垂直分辨率&#xff1a;8位 自动缩放和峰值检测 有见地的…

数据分类:成功DLP的基本要求

现如今我们存储数据的方式发生了巨大变化&#xff0c;从优质硬盘到今天的云存储解决方案&#xff0c;存储技术的进步大幅削减了成本&#xff0c;并使组织能够呈指数级增长的数据&#xff0c;我们都在利用这一点。 事实上&#xff0c;数据每年以惊人的 25% 的速度增长&#xff…

顶级PCVR头显具备什么配置?清晰度如何?

头戴式显示器是VR体验中用户与虚拟现实环境交互不可或缺的一部分。高端的头显通常可为使用者提供具有超高分辨率的高清画面&#xff0c;因此当你拥有一部高端的VR头显&#xff0c;虚拟世界将如真实世界一样呈现在你眼前。 说到顶级头显我们就不得不提到Varjo&#xff0c;Varjo是…