一、引言

在移动应用中,进度展示是一个无处不在的交互模式。从文件下载的百分比、视频播放的进度条,到健康目标的完成度、任务执行的状态指示——进度条和进度环以最简洁的视觉语言传递"完成了多少、还剩多少"的信息。

ArkUI 提供了 Progress 组件,覆盖了几乎所有常见的进度展示形态:线性进度条(Linear)、环形进度环(Ring)、月牙形(Eclipse)、胶囊形(Capsule)和刻度环(ScaleRing)。与传统的自定义绘制不同,Progress 组件将这些形态统一在一个 API 下,通过 type 参数切换样式,通过 valuetotal 控制进度,通过 colorbackgroundColor 定制视觉。

Progress 的另一个核心特性是色彩映射——进度的颜色不一定是固定的,它可以随着百分比的增长动态变化。这意味着进度条不仅是"信息的载体",它本身就可以成为"信息的表达"——从红色(危险/落后)到黄色(警告/接近)到绿色(完成/达标),用户不看数字也能感知状态。

本文将通过一个完整的**“每日目标追踪”**实战案例,深入解析 Progress 组件的各种类型、色彩映射策略以及与用户操作的交互模式。阅读完本文,你将能够:

  • 掌握 Progress 的五种类型及其适用场景
  • 理解 valuetotalcolor 等核心属性的配置方式
  • 学会 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 类型widthheight 共同决定了环形的大小——环会自动居中在给定的矩形区域内,直径取两者中的较小值。对于 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 页面整体设计

目标追踪器围绕四个典型的日常目标设计:

  1. 运动步数 — 目标 10000 步,步进 1000 步
  2. 阅读时长 — 目标 60 分钟,步进 10 分钟
  3. 饮水杯数 — 目标 8 杯,步进 1 杯
  4. 睡眠时长 — 目标 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}目标达成!`);
  }
}

这里的关键设计:

  1. 不可变更新(符合 ArkTS @State 要求):创建全新的 updated 数组,修改过的目标创建全新的对象,未修改的直接引用原对象。

  2. 上限控制Math.min(val, target * 1.5) 防止用户无限累加。1.5 倍的上限允许"超额完成"的满足感,同时防止数值失控。

  3. 目标达成提示:当更新后的值超过目标值时,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 和实战应用。

回顾本文覆盖的核心要点:

  1. 五种进度类型:Linear(线性条)、Ring(环形)、Eclipse(月牙形)、Capsule(胶囊形)、ScaleRing(刻度环),通过 type 参数切换,覆盖几乎所有进度展示需求。

  2. 核心参数value(当前值)和 total(目标值)控制进度百分比,value 可以超过 total

  3. 双层着色color 控制填充色,backgroundColor 控制轨道色。两者配合可实现丰富的视觉表达。

  4. 动态色彩映射:基于百分比的阶梯式颜色切换(灰→橙→黄→蓝→绿),让进度条本身成为一种"信息编码",用户不看数字也能感知状态。

  5. Ring + Linear 组合:环形用于单个指标的直观展示(视觉焦点),线性用于总体进度和空间高效利用(信息密度)。两种类型在同一页面中发挥不同作用。

  6. 不可变数据更新:在增减操作中,通过创建新数组和新对象来更新 @State 变量,确保 ArkUI 的声明式刷新机制正常运作。

Progress 是 ArkUI 中最"安静"却又最"无处不在"的组件之一。它不参与用户的直接输入,不产生事件回调,不管理复杂状态——它只是忠实地展示一个数值占总量的比例。但正是这种"沉默的诚实",让它成为数据可视化中最可靠的伙伴。当你的应用需要告诉用户"进行到哪了",Progress 永远是最直接、最优雅的答案。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐