HarmonyOS 6.0 进度条与环形进度

📅 2026/7/21 12:02:45
HarmonyOS 6.0 进度条与环形进度
进度条看起来简单但HarmonyOS的Progress组件有五种类型每种适用场景不同。选错了类型体验就很怪——比如用Linear做圆形仪表盘或者用Ring做横向下载进度。这篇把五种类型全过一遍再讲自定义环形进度的Canvas实现。Progress组件五种类型Progress({value:50,total:100,type:ProgressType.Linear})类型外观典型场景Linear横向矩形条下载进度、表单完成度Ring圆环百分比仪表盘、加载等待Eclipse圆形遮罩裁剪图片加载、闪屏过渡ScaleRing带刻度圆环速度表、功率仪表Capsule胶囊形(圆角矩形)步数进度、目标达成value是当前值total是总值。value/total就是完成比例。Linear——线性进度条Progress({value:75,total:100,type:ProgressType.Linear}).width(100%).height(8).color(#1a73e8).backgroundColor(#e0e0e0).borderRadius(4)最基础的横向进度条。height控制粗细8vp是常见值。borderRadius让两端圆滑。color是进度颜色backgroundColor是轨道颜色。Linear适合所有从左到右推进的场景——下载、上传、表单填写、测试执行。不够酷但最实用。Ring——圆环进度Progress({value:75,total:100,type:ProgressType.Ring}).width(160).height(160).color(#1a73e8).backgroundColor(#e0e0e0).style({strokeWidth:12})Ring是空心圆环。strokeWidth控制环的粗细。圆环中间是空的通常在中间放一个Text显示百分比Stack(){Progress({value:this.progress,total:100,type:ProgressType.Ring}).width(160).height(160).color(#1a73e8).style({strokeWidth:12})Text(this.progress.toString()%).fontSize(28).fontWeight(FontWeight.Bold).fontColor(#333333)}Stack叠加Progress和TextText在中间显示百分比。这是最常见的仪表盘模式。Ring的起始点是12点方向顺时针推进。这个方向不能改。Eclipse——遮罩裁剪进度Progress({value:50,total:100,type:ProgressType.Eclipse}).width(80).height(80).color(#1a73e8)Eclipse是圆形遮罩效果——一个圆从左到右被揭露出来。不是环形而是实心圆未完成部分被遮罩。这个类型用得最少主要做图片加载过渡或者闪屏动画。不显示具体数值只是视觉上逐渐露出的效果。ScaleRing——刻度圆环Progress({value:60,total:100,type:ProgressType.ScaleRing}).width(120).height(120).color(#ff9800).backgroundColor(#f5f5f5).style({strokeWidth:16,scaleCount:12,scaleWidth:2})ScaleRing在Ring基础上加了刻度线scaleCount刻度数量12表示每30度一个刻度scaleWidth刻度线宽度strokeWidth环粗细仪表盘风格适合速度表、温度计等需要刻度感的场景。Capsule——胶囊进度Progress({value:7000,total:10000,type:ProgressType.Capsule}).width(100%).height(24).color(#43a047)Capsule是圆角矩形进度条两端都是半圆。比Linear更圆润适合步数进度、目标达成这种可爱场景。24vp高度时胶囊效果最明显。高度太低看起来跟Linear差不多。style参数style是Progress的细调参数不同类型支持不同的style字段参数类型适用说明strokeWidthLengthRing/ScaleRing环宽度scaleCountnumberScaleRing刻度数量scaleWidthLengthScaleRing刻度线宽度enableSmoothEffectboolean所有是否启用平滑过渡enableSmoothEffecttrue时value变化有过渡动画false时直接跳到新值。默认true。动态进度更新用setInterval模拟进度增长Stateprogress:number0privatetimer:number-1startProgress():void{this.progress0;this.timersetInterval((){if(this.progress100){this.progress1;}else{clearInterval(this.timer);}},30);}aboutToDisappear():void{if(this.timer!-1){clearInterval(this.timer);}}每30ms增长1%100%时停止。30ms * 100 3秒完成。clearInterval在aboutToDisappear中清理避免内存泄漏。自定义环形进度——Canvas实现Progress组件的Ring样式有限——不能调起始角度、不能画渐变色、不能加刻度文字。需要自定义时用CanvasprivatedrawRingProgress(value:number,total:number):void{letctx:CanvasRenderingContext2Dthis.context;letcenterX:number100;letcenterY:number100;letradius:number70;letlineWidth:number12;ctx.clearRect(0,0,200,200);// 背景环ctx.beginPath();ctx.arc(centerX,centerY,radius,0,2*Math.PI);ctx.strokeStyle#e0e0e0;ctx.lineWidthlineWidth;ctx.lineCapround;ctx.stroke();// 进度环letratio:numbervalue/total;letstartAngle:number-Math.PI/2;letendAngle:numberstartAngleratio*2*Math.PI;ctx.beginPath();ctx.arc(centerX,centerY,radius,startAngle,endAngle);ctx.strokeStyle#1a73e8;ctx.lineWidthlineWidth;ctx.lineCapround;ctx.stroke();}lineCapround’让进度端点圆滑。startAngle-PI/2从12点方向开始。跟Progress的Ring效果一样但可以自由定制。渐变色环形进度// 用createLinearGradient创建渐变letgradient:CanvasGradientctx.createLinearGradient(centerX-radius,centerY,centerXradius,centerY);gradient.addColorStop(0,#1a73e8);gradient.addColorStop(1,#43a047);ctx.strokeStylegradient;createLinearGradient创建水平渐变起点蓝色到终点绿色。addColorStop的offset从0到1。渐变方向是固定的linearGradient——即使圆环转了一圈渐变还是从左到右。要实现跟随角度的渐变需要分段绘制。多段进度一个环显示多种数据占比letsegments:number[][30,20,25,25];letcolors:string[][#1a73e8,#43a047,#ff9800,#e53935];letangle:number-Math.PI/2;for(leti:number0;isegments.length;i){letsweep:number(segments[i]/100)*2*Math.PI;ctx.beginPath();ctx.arc(centerX,centerY,radius,angle,anglesweep);ctx.strokeStylecolors[i];ctx.lineWidthlineWidth;ctx.stroke();anglesweep;}每段画一段弧不同颜色。段之间没有间隔。要加间隔的话在angle上加一个小偏移。确定态vs不确定态进度有两种状态确定态知道具体进度下载50%显示具体value不确定态不知道进度网络请求中value设0或用LoadingProgress// 不确定态LoadingProgress().width(48).height(48).color(#1a73e8)LoadingProgress是专门的等待指示器显示持续旋转动画。没有具体的进度值纯粹告诉用户在加载中。踩坑清单问题原因解决Ring中间没文字Progress不支持内部文字用Stack叠加TextEclipse看不出进度value太小或total太大调整value/total比例Capsule跟Linear一样height太小height20vp进度跳变不平滑enableSmoothEffectfalse默认true不要关Canvas环形起点不在顶部起始角度0在3点方向用-PI/2从12点开始setInterval泄漏aboutToDisappear没清理加clearInterval渐变方向不对createLinearGradient坐标固定分段绘制或用conicGradientScaleRing刻度不清晰scaleCount太多或strokeWidth太小scaleCount20, strokeWidth8Progress颜色不支持渐变color只接受ResourceColor用Canvas自定义实现value超过total进度超过100%clamp value total进度条选择很简单横着的用Linear圆的用Ring酷的用Capsule要刻度用ScaleRing不够用Canvas。别想太复杂。