HarmonyOS 6.0 自定义下拉刷新与上拉加载
列表没有下拉刷新就像网页没有F5——用户刷新不了数据总觉得看到的是旧内容。HarmonyOS的Refresh组件能做基础刷新但真要做出下拉→弹性动画→加载中→收起的完整体验默认配置远远不够。上拉加载更是没有内置支持得自己从头撸。Refresh组件基础最简单的下拉刷新StateisRefreshing:booleanfalseRefresh({refreshing:$$this.isRefreshing}){List(){ForEach(this.items,(item:DataItem){ListItem(){Text(item.title)}},(item:DataItem)item.id)}}.onRefreshing((){this.loadData();})$$this.isRefreshing是双向绑定——Refresh组件会自动设为true触发刷新数据加载完后设为false收起。onRefreshing是刷新触发回调。问题Refresh的默认动画太简陋——就一个圈在转没有弹性下拉效果没有文字提示没有成功/失败反馈。自定义刷新布局用Refresh的builder参数自定义刷新区域StateisRefreshing:booleanfalseStaterefreshState:stringidleBuilderrefreshBuilder(){Row(){if(this.refreshStateidle){Text(下拉刷新).fontSize(14).fontColor(#999999)}elseif(this.refreshStatepulling){Text(释放立即刷新).fontSize(14).fontColor(#666666)}elseif(this.refreshStaterefreshing){LoadingProgress().width(20).height(20).margin({right:8})Text(正在刷新...).fontSize(14).fontColor(#1a73e8)}elseif(this.refreshStatesuccess){Text(刷新成功).fontSize(14).fontColor(#43a047)}elseif(this.refreshStatefailed){Text(刷新失败请重试).fontSize(14).fontColor(#e53935)}}.width(100%).height(60).justifyContent(FlexAlign.Center).alignItems(VerticalAlign.Center)}Refresh({refreshing:$$this.isRefreshing,builder:this.refreshBuilder()}){List(){// 列表内容}}.onRefreshing(async(){this.refreshStaterefreshing;try{awaitthis.loadData();this.refreshStatesuccess;}catch(e){this.refreshStatefailed;}setTimeout((){this.isRefreshingfalse;this.refreshStateidle;},500);})五个状态idle→pulling→refreshing→success/failed→idle。成功和失败显示500ms后收起。下拉距离监听Refresh组件的onPullingDown回调提供下拉距离Refresh({refreshing:$$this.isRefreshing}){List(){// 内容}}.onPullingDown((progress:number){if(progress0.6this.refreshState!refreshing){this.refreshStateidle;}elseif(progress0.6this.refreshState!refreshing){this.refreshStatepulling;}})progress是0~1的进度值0表示未下拉1表示到达触发阈值。0.6是个经验值——下拉超过60%时提示释放刷新。自定义旋转箭头下拉时箭头随进度旋转StatepullProgress:number0BuilderrefreshBuilder(){Row(){Image($r(sys.media.ohos_ic_public_arrow_down)).width(20).height(20).rotate({angle:this.pullProgress*180}).animation({duration:100}).margin({right:8})if(this.refreshStaterefreshing){LoadingProgress().width(20).height(20).margin({right:8})Text(加载中...)}elseif(this.pullProgress0.6){Text(释放刷新)}else{Text(下拉刷新)}}.fontSize(14).fontColor(#666666).width(100%).height(60).justifyContent(FlexAlign.Center)}.onPullingDown((progress:number){this.pullProgressprogress;// 状态判断})pullProgress从0到1箭头旋转0°到180°。超过阈值时箭头朝上提示释放刷新。上拉加载更多HarmonyOS没有内置上拉加载需要自己实现。最简单的方式是在List底部加一个加载触发器StateisLoadingMore:booleanfalseStatehasMore:booleantrueprivatecurrentPage:number1List(){ForEach(this.items,(item:DataItem){ListItem(){// 列表项内容}},(item:DataItem)item.id)// 底部加载指示器if(this.hasMore){ListItem(){Row(){LoadingProgress().width(20).height(20).margin({right:8})Text(加载更多...).fontSize(14).fontColor(#999999)}.width(100%).height(50).justifyContent(FlexAlign.Center)}}else{ListItem(){Text(没有更多了).fontSize(14).fontColor(#cccccc).width(100%).textAlign(TextAlign.Center).padding(16)}}}.onReachEnd((){if(!this.isLoadingMorethis.hasMore){this.loadMore();}})onReachEnd在列表滚动到底部时触发。isLoadingMore防止重复触发hasMore判断是否还有更多数据。loadMore的实现privateasyncloadMore():Promisevoid{this.isLoadingMoretrue;this.currentPage;try{letnewItemsawaitthis.fetchData(this.currentPage);if(newItems.length0){this.hasMorefalse;}else{this.itemsthis.items.concat(newItems);}}catch(e){this.currentPage--;}this.isLoadingMorefalse;}concat合并新旧数据。新数据为空说明到底了设hasMorefalse。手动触发加载更多onReachEnd在快速滚动时可能不触发。可以用onScrollIndex作为补充.onScrollIndex((start:number,end:number){if(endthis.items.length-3!this.isLoadingMorethis.hasMore){this.loadMore();}})距离底部3条数据时提前加载实现预加载效果。用户看到最后几条时新数据已经准备好了。空状态处理首次加载和刷新后都可能有空结果if(this.items.length0){Column(){if(this.isFirstLoad){LoadingProgress().width(40).height(40).margin({bottom:16})Text(加载中...).fontSize(14).fontColor(#999999)}else{Image($r(app.media.empty_state)).width(120).height(120).margin({bottom:16})Text(暂无数据).fontSize(16).fontColor(#999999).margin({bottom:8})Text(点击重试).fontSize(14).fontColor(#1a73e8).onClick((){this.isRefreshingtrue;this.loadData();})}}.width(100%).height(100%).justifyContent(FlexAlign.Center)}else{Refresh({refreshing:$$this.isRefreshing}){List(){// 列表内容}}.onRefreshing((){this.loadData();})}首次加载显示loading加载完成无数据显示空状态重试按钮。有数据时才显示列表。刷新与加载的协调下拉刷新应该重置分页状态privateasyncloadData():Promisevoid{this.currentPage1;this.hasMoretrue;try{this.itemsawaitthis.fetchData(1);this.refreshStatesuccess;}catch(e){this.refreshStatefailed;}setTimeout((){this.isRefreshingfalse;this.refreshStateidle;},500);}刷新时currentPage重置为1hasMore恢复trueitems用新数据替换不是concat。加载更多时才concat追加。关键刷新和加载更多不能同时进行。在isRefreshing为true时禁止触发loadMore在isLoadingMore为true时不响应onRefreshing。列表滚动位置记忆刷新后列表会跳回顶部。要保持位置privatescroller:ScrollernewScroller();privatescrollOffset:number0;List(){// 内容}.scroller(this.scroller).onScroll((){this.scrollOffsetthis.scroller.currentOffset().yOffset;})// 刷新完成后恢复位置asyncloadData():Promisevoid{letsavedOffsetthis.scrollOffset;this.currentPage1;this.itemsawaitthis.fetchData(1);this.isRefreshingfalse;// 恢复滚动位置setTimeout((){this.scroller.scrollTo({xOffset:0,yOffset:savedOffset});},100);}刷新前记录currentOffset刷新后scrollTo恢复。setTimeout 100ms等UI更新完成再滚动。但大多数应用刷新后跳回顶部是预期行为——用户下拉刷新就是想看最新内容。只有静默刷新后台刷新不跳位置才需要记忆位置。踩坑清单问题原因解决刷新动画收不起来isRefreshing没设回falseloadData完成后设false下拉没有弹性没用Refresh组件用Refresh包裹List加载更多重复触发没用isLoadingMore防重加布尔锁没有更多数据还触发hasMore没判断加hasMore标记刷新时触发加载更多两个状态没互斥isRefreshing时禁止loadMoreonReachEnd不触发LazyForEach缓存不够用onScrollIndex提前触发空状态没显示只判断items空没判断加载状态区分首次加载和加载完成刷新后列表跳顶这是默认行为如需保持用scroller记忆位置自定义builder不显示builder参数写法错builder: this.xxxBuilder()下拉进度不准确onPullingDown的progress是0~1progress0.6为可触发下拉刷新用Refresh自定义builder上拉加载用onReachEnd分页控制。两者共享数据源但状态独立——刷新重置分页加载追加数据。记住这个原则任何列表的刷新加载都能搞定。

相关新闻

Qlib平台:AI赋能量化投资的开源解决方案

Qlib平台:AI赋能量化投资的开源解决方案

1. Qlib平台概述Qlib是一个由微软研究院开发的AI赋能量化投资开源平台,它彻底改变了传统量化研究的范式。作为一个完整的技术栈解决方案,Qlib将金融数据科学、机器学习和投资决策流程无缝整合。我在实际使用中发现,它特别适合那些希望将前沿A…

2026/10/15 11:55:21 阅读更多 →
C++代码混淆的未来:obfy框架的扩展与定制方法

C++代码混淆的未来:obfy框架的扩展与定制方法

C代码混淆的未来:obfy框架的扩展与定制方法 【免费下载链接】obfy A tiny C obfuscation framework 项目地址: https://gitcode.com/gh_mirrors/ob/obfy obfy是一款轻量级C代码混淆框架(A tiny C obfuscation framework),旨…

2026/10/15 11:55:27 阅读更多 →
轴承故障诊断:OCSSA-VMD-CNN-BiLSTM优化方案

轴承故障诊断:OCSSA-VMD-CNN-BiLSTM优化方案

1. 轴承故障诊断技术背景与挑战轴承作为旋转机械的核心部件,其运行状态直接影响设备整体可靠性。根据行业统计,约40%的旋转机械故障源于轴承失效,而早期故障诊断能减少高达75%的意外停机损失。传统诊断方法主要依赖振动信号分析,但…

2026/10/15 12:25:03 阅读更多 →

最新新闻

MiniCPM-V 4.7端侧推理实测:35B MoE模型在iPhone 17 Pro Max上的真实体验

MiniCPM-V 4.7端侧推理实测:35B MoE模型在iPhone 17 Pro Max上的真实体验

人工智能大模型多模态基础模型本地部署 【免费下载链接】MiniCPM-V-4.7-35B-A3B MiniCPM-V 4.7 是 MiniCPM-V 系列的最新模型,提供 35B-A3B 变体,其中 35B-A3B 是 MiniCPM-V 系列中的首个 MoE(混合专家)模型。它在家族现有的单图、…

2026/10/15 17:51:06 阅读更多 →
多项式环中的公因式、因式分解与重因式解析

多项式环中的公因式、因式分解与重因式解析

1. 这不是“背公式”的章节,而是代数思维的分水岭如果你翻过《高等代数》教材第7章,看到“公因式”“因式分解”“重因式”这几个词,第一反应可能是:这不就是中学多项式除法的升级版?再套个“环”的帽子,加…

2026/10/15 17:51:06 阅读更多 →
ViTPose 仓库实战:HRNet + DarkPose 在 COCO-WholeBody 全身关键点估计中的配置与训练指南

ViTPose 仓库实战:HRNet + DarkPose 在 COCO-WholeBody 全身关键点估计中的配置与训练指南

人工智能计算机视觉深度学习 【免费下载链接】ViTPose The official repo for [NeurIPS22] "ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation" and [TPAMI23] "ViTPose: Vision Transformer for Generic Body Pose Estimation" 项…

2026/10/15 17:51:06 阅读更多 →
GPCHC二进制帧解析与ROS话题发布:从串口到NavSatFix驱动实战

GPCHC二进制帧解析与ROS话题发布:从串口到NavSatFix驱动实战

简介:针对huace GPCHC解析与ROS集成这一具体场景,资源面向从事机器人定位、无人系统导航开发的工程师与研究者,重点解决GPS原始数据如何在机器人操作系统中完成采集、解析、转换与发布的问题。包体为一个约20.56MB的zip压缩包,内容…

2026/10/15 17:51:06 阅读更多 →
Spring Boot名士会所会员管理系统:从开发实战到答辩通关全指南

Spring Boot名士会所会员管理系统:从开发实战到答辩通关全指南

1. 这到底是个什么项目:先看清楚它的真实定位 第一次看到“springboot名士会所会员管理系统”这个标题,我的第一反应是:这不是一个简单的CRUD堆积品,而是一套带有真实商业场景的会员运营后台。所谓的“名士会所”,其实…

2026/10/15 17:51:06 阅读更多 →
Cesium自建地形数据实战:从DEM到量化网格瓦片

Cesium自建地形数据实战:从DEM到量化网格瓦片

搞Cesium开发,最绕不开的一件事就是地形数据。默认的在线地形服务虽然打开就能用,可真到了项目落地,总有让你必须自己生成地形数据的理由——精度不够、网络受限、数据不能离开本机。这篇博客把完整跑过一次的Cesium地形数据生成过程记录下来…

2026/10/15 17:50:05 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →