鸿蒙新特性——Progress 进度组件深度解析
一、引言
在移动应用中,进度展示是一个无处不在的交互模式。从文件下载的百分比、视频播放的进度条,到健康目标的完成度、任务执行的状态指示——进度条和进度环以最简洁的视觉语言传递"完成了多少、还剩多少"的信息。
ArkUI 提供了 Progress 组件,覆盖了几乎所有常见的进度展示形态:线性进度条(Linear)、环形进度环(Ring)、月牙形(Eclipse)、胶囊形(Capsule)和刻度环(ScaleRing)。与传统的自定义绘制不同,Progress 组件将这些形态统一在一个 API 下,通过 type 参数切换样式,通过 value 和 total 控制进度,通过 color 和 backgroundColor 定制视觉。
Progress 的另一个核心特性是色彩映射——进度的颜色不一定是固定的,它可以随着百分比的增长动态变化。这意味着进度条不仅是"信息的载体",它本身就可以成为"信息的表达"——从红色(危险/落后)到黄色(警告/接近)到绿色(完成/达标),用户不看数字也能感知状态。
本文将通过一个完整的**“每日目标追踪”**实战案例,深入解析 Progress 组件的各种类型、色彩映射策略以及与用户操作的交互模式。阅读完本文,你将能够:
- 掌握 Progress 的五种类型及其适用场景
- 理解
value、total、color等核心属性的配置方式 - 学会 Ring 环形进度与 Linear 线性进度的组合使用
- 实现基于百分比的动态色彩映射
- 构建完整的增/减/重置操作流程
二、Progress 组件核心 API 详解
2.1 构造函数与类型系统
Progress 的构造函数接受三个核心参数:
Progress(options: {
value: number; // 当前进度值
total?: number; // 总进度值,默认为 100
type?: ProgressType; // 进度类型,默认为 ProgressType.Linear
})
ArkUI 支持五种进度类型:
| 类型 | 枚举值 | 视觉效果 | 适用场景 |
|---|---|---|---|
| 线性条 | ProgressType.Linear |
水平填充条 | 文件下载、表单步骤、加载进度 |
| 环形 | ProgressType.Ring |
圆环填充弧 | 目标达成度、存储空间、健康指标 |
| 月牙形 | ProgressType.Eclipse |
半圆弧线 | 速度表、评分展示、简约仪表 |
| 胶囊形 | ProgressType.Capsule |
圆角厚条 | 大按钮内嵌进度、醒目的单一指标 |
| 刻度环 | ProgressType.ScaleRing |
带刻度的环形 | 精确仪表、分档指标 |
在我们的目标追踪 Demo 中,主要使用了 Ring(环形)和 Linear(线性)两种类型:
// 环形进度 —— 展示单项目标的完成百分比
Progress({ value: goal.current, total: goal.target, type: ProgressType.Ring })
.width(56)
.height(56)
.color(this.getProgressColor(goal.current, goal.target))
.backgroundColor('#F0F0F5')
// 线性进度 —— 展示总体完成度和单项进度
Progress({ value: this.getOverallPercent(), total: 100, type: ProgressType.Linear })
.width('100%')
.height(10)
.color('#52C41A')
.backgroundColor('#FFFFFF33')
Ring 和 Linear 的组合设计是有意图的:Ring 提供直观的"单个指标视觉",Linear 提供高效的"空间利用"和"横向对比能力"。在同一个页面中使用两种类型,既丰富了视觉层次,也为用户提供了两种不同的信息读取方式。
2.2 value 与 total:进度计算
value 表示当前已完成的量,total 表示完成所需的全部量。进度百分比的计算方式为 (value / total) * 100。
特别需要注意的是:value 可以超过 total。当 value > total 时,进度条会显示为满格状态(100%),但实际百分比可以超过 100%。在我们的 Demo 中,这是通过 Math.min(current / target, 1) 来限制的:
getPercent(current: number, target: number): number {
const pct: number = Math.min(current / target, 1) * 100;
return Math.round(pct);
}
Math.min(...) 确保显示的百分比不会超过 100%,但用户可以通过 + 按钮将当前值增加到目标的 1.5 倍(在 incrementGoal 中)。这种设计允许用户"超额完成"目标——展示的百分比虽然停在 100%,但实际数值会被保留并显示。
2.3 color 与 backgroundColor:双层着色
Progress 组件使用两种颜色来控制视觉呈现:
- color:填充部分的颜色。对于 Linear 是已填充的条,对于 Ring 是已填充的弧。
- backgroundColor:轨道/背景部分的颜色。对于 Linear 是未填充的底色,对于 Ring 是未填充的弧底色。
在我们的 Demo 中,color 并非固定值,而是通过 getProgressColor() 动态计算:
getProgressColor(current: number, target: number): string {
const pct: number = this.getPercent(current, target);
if (pct >= 100) return '#52C41A'; // 绿色:已完成
if (pct >= 75) return '#1677FF'; // 蓝色:接近完成
if (pct >= 50) return '#FAAD14'; // 黄色:过半
if (pct >= 25) return '#FF7A45'; // 橙色:刚开始
return '#C9CDD4'; // 灰色:几乎没动
}
这种阶梯式色彩映射实现了一种"非语言的信息传达":用户不需要阅读百分比数字,仅凭颜色就能判断每个目标的完成状态。灰色的进度环意味着"需要行动",绿色的进度环意味着"已经完成",这是一种比数字更直觉的交互语言。
2.4 width 与 height:尺寸控制
Progress({ value: 75, total: 100, type: ProgressType.Ring })
.width(56) // 环形直径
.height(56)
Progress({ value: 75, total: 100, type: ProgressType.Linear })
.width('100%') // 填充容器宽度
.height(10) // 线条高度
对于 Ring 类型,width 和 height 共同决定了环形的大小——环会自动居中在给定的矩形区域内,直径取两者中的较小值。对于 Linear 类型,width 决定长度,height 决定粗细。
在我们的页面中,环形的尺寸是 56×56vp,小巧到可以放在每个目标行右侧,不抢占主要信息的空间;而线性进度使用 width('100%') 占满容器,体现"总体进度"的全局视角。
2.5 borderRadius:圆角控制
.borderRadius(5) // 适用于 Linear 类型
对于线性进度条,borderRadius 控制条的两端是否为圆角。较大的圆角值(如 5vp)会让进度条看起来更柔和;设为 0 则是平直的矩形。对于环形进度,这个属性不适用(环已经是天然的弧线)。
2.6 style 对象(部分 API 版本)
在一些 ArkUI 版本中,Progress 支持通过 style 对象进行更精细的控制:
Progress({ value: 75, type: ProgressType.Ring })
.style({
strokeWidth: 8, // 环的线宽
scaleCount: 20, // ScaleRing 的刻度数
scaleWidth: 2, // ScaleRing 的刻度宽度
strokeLinecap: 'round' // 端点样式:round 或 butt
})
strokeWidth 是控制环粗细的关键属性——较细的环(4-6vp)显得精致,较粗的环(10-14vp)更有视觉重量。我们的 Demo 中使用默认的 strokeWidth,没有显式设置。
三、实战:每日目标追踪
3.1 页面整体设计
目标追踪器围绕四个典型的日常目标设计:
- 运动步数 — 目标 10000 步,步进 1000 步
- 阅读时长 — 目标 60 分钟,步进 10 分钟
- 饮水杯数 — 目标 8 杯,步进 1 杯
- 睡眠时长 — 目标 8 小时,步进 0.5 小时
每个目标展示三组信息:环形进度图(视觉概览)、当前/目标数值(精确数据)、± 操作按钮(交互入口)。页面顶部有总体完成度的线性进度条和百分比数字,底部有"重置全部目标"和"全部加满"两个批量操作按钮。
3.2 数据模型与状态管理
interface GoalItem {
label: string;
icon: string;
current: number;
target: number;
unit: string;
step: number;
color: string;
}
@State goals: GoalItem[] = [
{ label: '运动步数', icon: '🚶', current: 3200, target: 10000, unit: '步', step: 1000, color: '#1677FF' },
{ label: '阅读时长', icon: '📖', current: 25, target: 60, unit: '分钟', step: 10, color: '#52C41A' },
{ label: '饮水杯数', icon: '💧', current: 4, target: 8, unit: '杯', step: 1, color: '#1677FF' },
{ label: '睡眠时长', icon: '😴', current: 5.5, target: 8, unit: '小时', step: 0.5, color: '#722ED1' },
];
每个字段的含义:
current:当前累计值。初始值设定为"已经完成了一部分"的状态,让用户看到半满的进度条,而不是全空的起点——这在 Demo 演示中更具吸引力。target:目标值。不同目标有不同的量纲和数量级(步数以千计,杯数以个计),体现了 Progress 对不同数值范围的适应能力。step:每次 ± 按钮的增量。步进值的选择反映了该目标的性质——步数以千为单位递增(因为用户通常一次走很多步),杯数以 1 为单位递增(因为每次喝一杯水),睡眠以 0.5 小时为单位(更精细的增量)。color:目标的主色调。注意这个 color 不是进度条的填充色(填充色由getProgressColor动态计算),而是 + 按钮的背景色和目标标识色,用于在不同的目标卡片之间建立视觉区分。
3.3 增量与减量操作
每个目标配备 − 和 + 两个按钮,同时修改 current 值并触发 UI 刷新:
incrementGoal(index: number): void {
const updated: GoalItem[] = [];
for (let i = 0; i < this.goals.length; i++) {
if (i === index) {
const newCurrent: number = Math.min(
this.goals[i].current + this.goals[i].step,
this.goals[i].target * 1.5 // 上限:目标的 1.5 倍
);
updated.push({
label: this.goals[i].label, icon: this.goals[i].icon,
current: newCurrent, target: this.goals[i].target,
unit: this.goals[i].unit, step: this.goals[i].step, color: this.goals[i].color
});
} else {
updated.push(this.goals[i]);
}
}
this.goals = updated;
if (updated[index].current >= updated[index].target) {
this.showToastMsg(`🎉 ${updated[index].label}目标达成!`);
}
}
这里的关键设计:
-
不可变更新(符合 ArkTS @State 要求):创建全新的
updated数组,修改过的目标创建全新的对象,未修改的直接引用原对象。 -
上限控制:
Math.min(val, target * 1.5)防止用户无限累加。1.5 倍的上限允许"超额完成"的满足感,同时防止数值失控。 -
目标达成提示:当更新后的值超过目标值时,Toast 提示"目标达成",给予用户正向激励。
减量操作 decrementGoal 使用 Math.max(val, 0) 保证数值不小于 0。
3.4 动态色彩映射详解
getProgressColor(current: number, target: number): string {
const pct: number = this.getPercent(current, target);
if (pct >= 100) return '#52C41A'; // 绿色
if (pct >= 75) return '#1677FF'; // 蓝色
if (pct >= 50) return '#FAAD14'; // 黄色
if (pct >= 25) return '#FF7A45'; // 橙色
return '#C9CDD4'; // 灰色
}
这个函数在三个地方被调用:
- 环形 Progress 的
color属性 - 线性 Progress 的
color属性 - 当前数值文字的颜色
三处同步使用同一个色彩映射函数,保证了视觉语言的一致性——你看到灰色的环,就意味着"几乎还没开始";看到绿色,就意味着"已经达成"。用户不需要在环形进度和数字之间来回比较,颜色已经传达了关键信息。
色彩阶梯设计遵循了通用的"交通灯"隐喻:
- 灰色(< 25%):未启动或刚起步,中性色不引起焦虑
- 橙色(25-50%):已进行中,温暖色给予鼓励
- 黄色(50-75%):已过半,醒目色提示进展良好
- 蓝色(75-100%):即将完成,冷静色暗示接近终点
- 绿色(≥ 100%):已完成,积极色确认达成
3.5 总体进度计算
getOverallPercent(): number {
let totalPct: number = 0;
for (let i = 0; i < this.goals.length; i++) {
totalPct += Math.min(this.goals[i].current / this.goals[i].target, 1);
}
return Math.round((totalPct / this.goals.length) * 100);
}
总体完成度是四个目标百分比的算术平均值。每个目标在总体中的权重相等——运动 50% + 阅读 80% + 饮水 25% + 睡眠 60% = 215% / 4 = 54%。
这个计算方式隐藏了一个设计假设:所有目标同等重要。如果实际产品中各目标重要性不同,可以引入权重参数进行调整。
3.6 批量操作
两个批量操作按钮位于页面底部:
- 重置全部目标:将所有 current 设为 0,彻底清空进度(模拟"新的一天开始")
- 全部加满:将所有 current 设为各自的 target,所有环形进度瞬间变绿(模拟"完美的一天")
"全部加满"是一个纯演示性的功能,但它非常有用:用户可以在几秒钟内体验从"几乎清零"到"全部完成"的完整状态切换,直观感受色彩映射的效果。在 Demo 展示中,这个按钮可以瞬间呈现页面最丰富的视觉状态。
四、完整代码结构
页面组件树:
Stack(根节点,用于 Toast 叠加)
└── Column
├── Row(标题栏:"📊 目标进度")
└── Scroll
└── Column
├── 总体进度卡片(深色背景)
│ ├── 完成度百分比 + 数值
│ └── Progress(Linear,100% 宽,10vp 高)
├── 目标卡片 × 4(白色背景)
│ ├── 标题行(图标 + 名称 + 说明)
│ ├── Progress(Ring,56×56,带百分比数字叠加)
│ └── 操作行(− 按钮 + 数值 + + 按钮 + Linear 进度条)
│ └── [可选] 达成标记
└── 操作区
├── Button "重置全部目标"
└── Button "全部加满"
代码约 230 行,核心聚焦 Progress 组件的 Ring 和 Linear 两种类型,以及基于百分比的动态色彩映射。
五、总结
本文以每日目标追踪为业务场景,深入解析了 ArkUI Progress 进度组件的核心 API 和实战应用。
回顾本文覆盖的核心要点:
-
五种进度类型:Linear(线性条)、Ring(环形)、Eclipse(月牙形)、Capsule(胶囊形)、ScaleRing(刻度环),通过
type参数切换,覆盖几乎所有进度展示需求。 -
核心参数:
value(当前值)和total(目标值)控制进度百分比,value可以超过total。 -
双层着色:
color控制填充色,backgroundColor控制轨道色。两者配合可实现丰富的视觉表达。 -
动态色彩映射:基于百分比的阶梯式颜色切换(灰→橙→黄→蓝→绿),让进度条本身成为一种"信息编码",用户不看数字也能感知状态。
-
Ring + Linear 组合:环形用于单个指标的直观展示(视觉焦点),线性用于总体进度和空间高效利用(信息密度)。两种类型在同一页面中发挥不同作用。
-
不可变数据更新:在增减操作中,通过创建新数组和新对象来更新
@State变量,确保 ArkUI 的声明式刷新机制正常运作。
Progress 是 ArkUI 中最"安静"却又最"无处不在"的组件之一。它不参与用户的直接输入,不产生事件回调,不管理复杂状态——它只是忠实地展示一个数值占总量的比例。但正是这种"沉默的诚实",让它成为数据可视化中最可靠的伙伴。当你的应用需要告诉用户"进行到哪了",Progress 永远是最直接、最优雅的答案。
更多推荐




所有评论(0)