HarmonyOS7 加载状态展示页实战:LoadingProgress 不只是会用,还要用得顺手 文章目录加载不只是转圈startLoading() 的关键是收尾按钮加载要防止重复提交页面结构怎么看完整代码写在最后加载状态最怕两种情况一种是用户点了按钮没反应以为卡死了另一种是 Loading 一直转用户不知道还要等多久。LoadingProgress本身不复杂难的是把它和真实任务状态绑在一起。这个 HarmonyOS7 页面把基础加载、按钮加载、任务进度和全屏遮罩放到一起看正好能覆盖日常开发里最常见的几种等待场景。加载不只是转圈页面里有isPageLoading、isButtonLoading、loadProgress和tasks。这几个状态分别对应页面级等待、按钮提交等待、进度条数值和任务列表。这样拆的好处是状态含义很清楚。按钮提交时只锁按钮不一定要遮住整个页面全屏加载适合页面初始化或关键操作任务进度则适合文件上传、资源下载这类可量化过程。startLoading()的关键是收尾startLoading()先把页面加载状态打开再用定时器模拟进度增长。真正值得注意的是到达 100 后的处理清理定时器、关闭加载态、把进度固定到 100。startLoading(){this.isPageLoadingtruethis.loadProgress0this.timersetInterval((){if(this.loadProgress100){clearInterval(this.timer)this.isPageLoadingfalsethis.loadProgress100}else{this.loadProgress5}},100)}做真实接口时也一样开始请求前进入 loading请求结束后一定要退出 loading。失败时也要退出不然用户会一直等下去。按钮加载要防止重复提交startButtonLoading()这种场景很常见登录、提交订单、保存表单。按钮一旦进入加载态就应该改变文案或显示加载图标同时避免用户连续点击。这里的重点不是动画而是交互承诺。用户点了按钮页面必须告诉他“我收到了正在处理”。页面结构怎么看LoadingStatePage分成基础 LoadingProgress、按钮加载、任务进度和全屏遮罩四块。读代码时可以先看状态字段再看两个启动方法最后看 UI 根据状态如何切换文案、进度和遮罩。如果你把这页改成真实业务我建议把模拟定时器换成接口回调或上传进度回调。加载状态要跟真实任务走别只做一个假动画。完整代码下面是完整代码。入口组件名是LoadingStatePage可以作为 HarmonyOS7 加载状态设计的参考页面。// LoadingProgress 加载动画interfaceLoadTask{id:numbername:stringprogress:numberstatus:stringcolor:string}EntryComponentstruct LoadingStatePage{StateisPageLoading:booleanfalseStateisButtonLoading:booleanfalseStateloadProgress:number0Statetasks:LoadTask[][{id:1,name:下载核心资源,progress:100,status:已完成,color:#059669},{id:2,name:加载用户数据,progress:75,status:加载中,color:#2563EB},{id:3,name:同步配置文件,progress:40,status:加载中,color:#D97706},{id:4,name:预加载图片缓存,progress:10,status:等待中,color:#9CA3AF},]privatetimer:number-1startLoading(){this.isPageLoadingtruethis.loadProgress0this.timersetInterval((){if(this.loadProgress100){clearInterval(this.timer)this.isPageLoadingfalsethis.loadProgress100}else{this.loadProgress5}},100)}startButtonLoading(){this.isButtonLoadingtruesetTimeout((){this.isButtonLoadingfalse},3000)}build(){Column({space:0}){// 顶部标题Text(LoadingProgress 加载动画).fontSize(20).fontWeight(FontWeight.Bold).fontColor(#111827).width(100%).padding({left:20,right:20,top:20,bottom:4})Text(展示各种加载状态场景下的最佳实践).fontSize(13).fontColor(#6B7280).width(100%).padding({left:20,right:20,bottom:16})// 一、内联加载动画Column({space:12}){Text(一、基础 LoadingProgress).fontSize(14).fontWeight(FontWeight.Bold).fontColor(#374151).width(100%)Row({space:24}){// 默认色Column({space:6}){LoadingProgress().width(40).height(40).color(#2563EB)Text(蓝色).fontSize(12).fontColor(#6B7280)}// 绿色Column({space:6}){LoadingProgress().width(40).height(40).color(#059669)Text(绿色).fontSize(12).fontColor(#6B7280)}// 橙色Column({space:6}){LoadingProgress().width(40).height(40).color(#D97706)Text(橙色).fontSize(12).fontColor(#6B7280)}// 大尺寸Column({space:6}){LoadingProgress().width(60).height(60).color(#7C3AED)Text(大号).fontSize(12).fontColor(#6B7280)}// 小尺寸Column({space:6}){LoadingProgress().width(24).height(24).color(#DC2626)Text(小号).fontSize(12).fontColor(#6B7280)}}.width(100%).justifyContent(FlexAlign.SpaceAround).padding({top:12,bottom:12}).backgroundColor(#F9FAFB).borderRadius(12)}.width(100%).padding({left:20,right:20}).alignItems(HorizontalAlign.Start).margin({bottom:16})// 二、按钮加载状态Column({space:12}){Text(二、按钮加载状态).fontSize(14).fontWeight(FontWeight.Bold).fontColor(#374151).width(100%)Row({space:12}){if(this.isButtonLoading){Button({type:ButtonType.Normal}){Row({space:8}){LoadingProgress().width(18).height(18).color(Color.White)Text(提交中...).fontSize(14).fontColor(Color.White)}}.backgroundColor(#2563EB).borderRadius(8).padding({left:20,right:20,top:10,bottom:10})}else{Button(提交表单).fontSize(14).backgroundColor(#2563EB).fontColor(Color.White).borderRadius(8).padding({left:20,right:20,top:10,bottom:10}).onClick(()this.startButtonLoading())}Text(this.isButtonLoading?3秒后恢复:点击触发加载).fontSize(12).fontColor(#9CA3AF)}.width(100%).alignItems(VerticalAlign.Center)}.width(100%).padding({left:20,right:20}).alignItems(HorizontalAlign.Start).margin({bottom:16})// 三、任务进度列表Column({space:12}){Text(三、任务进度展示).fontSize(14).fontWeight(FontWeight.Bold).fontColor(#374151).width(100%)Column({space:8}){ForEach(this.tasks,(task:LoadTask){Row(){if(task.progress100){LoadingProgress().width(20).height(20).color(task.progress10?#9CA3AF:task.color).margin({right:10})}else{Text(✅).fontSize(18).width(20).height(20).margin({right:10})}Column({space:4}){Row(){Text(task.name).fontSize(13).fontColor(#1F2937).layoutWeight(1)Text(task.status).fontSize(11).fontColor(task.progress100?#059669:task.color)}Progress({value:task.progress,total:100,type:ProgressType.Linear}).color(task.color).backgroundColor(#E5E7EB).style({strokeWidth:4})}.layoutWeight(1)}.width(100%).padding({left:12,right:12,top:10,bottom:10}).backgroundColor(#FAFAFA).borderRadius(8).alignItems(VerticalAlign.Center)},(task:LoadTask)task.id.toString())}}.width(100%).padding({left:20,right:20}).alignItems(HorizontalAlign.Start).margin({bottom:16})// 四、全屏蒙层加载Column({space:12}){Text(四、全屏遮罩加载).fontSize(14).fontWeight(FontWeight.Bold).fontColor(#374151).width(100%)Row({space:12}){Button(触发全屏加载).fontSize(13).backgroundColor(#7C3AED).fontColor(Color.White).borderRadius(8).padding({left:16,right:16,top:10,bottom:10}).onClick(()this.startLoading())if(this.loadProgress0){Text(${this.loadProgress}%).fontSize(16).fontWeight(FontWeight.Bold).fontColor(#7C3AED)}}.width(100%).alignItems(VerticalAlign.Center)}.width(100%).padding({left:20,right:20}).alignItems(HorizontalAlign.Start)Blank()// 全屏遮罩if(this.isPageLoading){Column({space:16}){LoadingProgress().width(60).height(60).color(Color.White)Text(加载中${this.loadProgress}%).fontSize(16).fontColor(Color.White)Progress({value:this.loadProgress,total:100,type:ProgressType.Linear}).width(160).color(Color.White).backgroundColor(rgba(255,255,255,0.3)).style({strokeWidth:4})}.width(100%).height(100%).backgroundColor(rgba(0,0,0,0.65)).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)}}.width(100%).height(100%).backgroundColor(#FFFFFF)}}写在最后加载状态展示页 这个案例的价值不在于用了多少组件而在于它把LoadingProgress放进了一个完整页面里。照着这个思路改自己的业务比单独背 API 更靠谱。