一、引言

星级评分是移动端应用中最常见的交互组件之一。从 App Store 的应用评分、豆瓣的电影打分,到电商平台的商品评价——五颗星不仅是数字的视觉化表达,更是用户情绪的快捷传递方式。在 HarmonyOS NEXT 之前,开发者若要实现星级评分,需要手动绘制 5 个 Image 组件、管理点击区域、计算分数——代码零散且容易出 Bug。

ArkUI 在 API 10 中新增了 Rating 组件,将星级评分的所有逻辑封装为一个独立组件:只需一行声明,就能获得支持交互式评分、只读展示、半星精度和自定义样式的完整评分体验。

本文通过一个影片评分 Demo深入讲解 Rating 组件的核心用法:如何区分交互式评分和只读展示?如何设置半星精度?如何自定义星星样式?以及如何在实际业务场景中将 Rating 融入用户交互流程。

阅读完本文,你将能够:

  • 使用 Rating 组件替代手工绘制的星级评分
  • 区分 indicator: true(只读)和 indicator: false(交互式)两种模式
  • stepSize 控制评分精度(1 = 整星,0.5 = 半星)
  • starStyle 自定义星星的前景、背景和次要图标
  • 将 Rating 组件的 onChange 事件融入真实的业务数据流

二、Rating 组件 API 总览

2.1 构造函数参数

Rating({ rating: 0, indicator: false })
参数 类型 说明
rating number 初始评分值,范围 0stars(默认 5)。默认为 0(无星)
indicator boolean 是否为指示器模式。true = 只读展示(不可交互),false = 可交互评分

rating 是外部传入的值,Rating 组件本身不会自动维护内部评分状态——它始终反映从外部传入的 rating 值。这意味着开发者需要自己维护评分状态,并在 onChange 回调中更新。

indicator 是 Rating 组件最关键的开关:

  • true:星星纯粹是视觉展示,用户点击和滑动都无效。适用于显示"社区平均评分""历史评分记录"等场景。
  • false:用户可以通过点击星星来改变评分。适用于"用户打分""当前评分"等交互场景。

2.2 属性方法

stars(count: number)

设置星星的总数,默认为 5。

Rating({ rating: 3 })
  .stars(5)  // 5颗星(默认值,可省略)

虽然可以设置任意星数(如 10),但 5 星是行业标准——App Store、豆瓣、亚马逊等主流平台均使用 5 星制。偏离这个标准会让用户感到困惑,因此不推荐修改。

stepSize(value: number)

设置评分的最小变化步长:

.stepSize(1)   // 仅支持整数评分:0, 1, 2, 3, 4, 5
.stepSize(0.5) // 支持半星评分:0, 0.5, 1, 1.5, ..., 5

stepSize(1) 是默认值,用户只能给出整数星。这在"快速评价"场景中足够用(5 选 1)。stepSize(0.5) 开启半星支持,用户可以给出 3.5 星这样的分数。半星的重要场景是"展示精确的平均分"——比如豆瓣电影 4.2 分,半星能精确到一位小数,信息量比只有整数星高出一倍。

步长值为 1 时的实际行为:用户点击第 3 颗星 → 分数变为 3;用户点击第 2 和第 3 颗星之间 → 分数仍为 3(因为步长限制为整数)。

starStyle(options: StarStyle)

自定义星星的图标样式:

.starStyle({
  backgroundUri: '',   // 未选中状态的星星图标
  foregroundUri: '',   // 选中状态的星星图标
  secondaryUri: ''     // 半选状态的星星图标
})

三个 URI 分别控制不同状态的星星外观。如果都不传(留空字符串),使用系统默认的黄色五角星。自定义 URI 可以是网络图片或本地资源路径。本 Demo 使用默认样式——系统原生星星在各种主题和屏幕上都有一致的外观。

2.3 事件回调

onChange(callback: (value: number) => void)

评分变化时触发。用户每次点击星星(在非 indicator 模式下),value 即为新的评分值。

Rating({ rating: movie.myRating, indicator: false })
  .onChange((v: number) => {
    this.rateMovie(movie.title, v);
  })

onChange 只在交互式模式(indicator: false)下有效。只读模式不会触发该回调,因为用户无法改变评分。
在这里插入图片描述

三、Demo 设计:影片评分页

3.1 功能概述

Demo 模拟一个影片评分页面,包含 4 部电影。每张电影卡片展示两组 Rating:

  • 豆瓣评分(只读):半星精度(stepSize: 0.5),展示社区平均分(如 4.2 分),橙色文字 + 评分数显示
  • 我的评分(交互式):整星精度(stepSize: 1),用户可点击打星,紫色文字 + 评分后显示"X星"

4 部电影覆盖不同的评分区间(3.7 到 4.6),让用户能够在多种场景下观察 Rating 的只读展示效果。

3.2 数据结构

interface MovieItem {
  title: string;       // 电影名
  year: string;        // 上映年份
  genre: string;       // 类型
  desc: string;        // 简介
  color: string;       // 海报占位色
  avgRating: number;   // 社区平均分(只读展示)
  totalRatings: number; // 评分数
  myRating: number;    // 用户评分(交互式评分)
}

4 部电影按 avgRating 从高到低排列:

电影 豆瓣均分 评分人数
哪吒之魔童闹海 4.6 35.6 万
流浪地球 3 4.2 18.5 万
长安三万里 3.9 12.4 万
飞驰人生 3 3.7 9.8 万

3.3 两种 Rating 模式的对比应用

每张电影卡片中,两组 Rating 同时存在但扮演不同角色:

只读模式的实现:

Rating({ rating: movie.avgRating, indicator: true })
  .stars(5)
  .stepSize(0.5)
  .width(120)
  .height(22)
  • indicator: true → 不可交互,纯粹展示社区评分
  • stepSize(0.5) → 半星精度,精确展示 4.2、3.7 等平均值
  • width(120) / height(22) → 控制星星所占空间,与文字标签对齐

只用 120vp 宽的 Rating 就能传递"这部电影口碑很好"的视觉信息——4.2 分显示为 4 颗满星 + 1/5 颗半星。视图尺寸小巧,适合放在"信息展示"区域而非"操作"区域。

交互式模式的实现:

Rating({ rating: movie.myRating, indicator: false })
  .stars(5)
  .stepSize(1)
  .width(160)
  .height(30)
  .onChange((v: number) => { this.rateMovie(movie.title, v); })
  • indicator: false → 可交互,用户点击改变评分
  • stepSize(1) → 仅整星,用户快速选择 1-5 星
  • width(160) / height(30) → 比只读模式更大,因为交互需要更大的触控区域
  • onChange → 评分变化时更新数据和 UI

交互式评分区分于只读展示的三个设计要点:

  1. 更大:160vp vs 120vp,为手指点击提供足够的触控面积
  2. 更高:30vp vs 22vp,避免星星太矮导致误触
  3. 更反馈:右侧文字实时显示"3星""4星"等评分结果,紫色加粗强调

3.4 评分回调与状态更新

rateMovie(title: string, rating: number): void {
  const newMovies: MovieItem[] = [];
  for (let i = 0; i < this.movies.length; i++) {
    const m = this.movies[i];
    if (m.title === title) {
      newMovies.push({
        title: m.title, year: m.year, genre: m.genre,
        desc: m.desc, color: m.color, avgRating: m.avgRating,
        totalRatings: m.totalRatings, myRating: rating
      });
    } else {
      newMovies.push(m);
    }
  }
  this.movies = newMovies;
}

不可变数组更新模式——遍历 4 部电影,只修改目标电影的 myRating 字段,其余保持不变。新数组整体赋值给 @State movies 触发 UI 刷新。

评分完成后展示 Toast 确认:

this.ratedMovie = title;
this.showToast = true;
const tid = setInterval(() => {
  clearInterval(tid);
  this.showToast = false;
}, 2000);

Toast 通过 Stackposition({ bottom: 80 }) 定位在页面底部中央,setInterval 在 2 秒后自动消失。这不是 Rating 组件的功能,而是对"评分成功"这一业务事件的视觉确认——让用户知道自己的评分已被记录。

3.5 页面结构

┌─────────────────────────────────────┐
│ ⭐ 影片评分(深色标题栏)             │
├─────────────────────────────────────┤
│ 📘 Rating 组件说明卡片               │
├─────────────────────────────────────┤
│ ┌───────────────────────────────┐   │
│ │ 🎬 哪吒之魔童闹海              │   │
│ │ 2025 · 动画/奇幻             │   │
│ │ 魔丸转世的哪吒在成长中...       │   │
│ │                               │   │
│ │ 豆瓣评分 ★★★★½ 4.6 分 (35.6万)│   │ ← 只读 Rating
│ │ ───────────────────────────── │   │
│ │ 我的评分 ★★★★☆ 4星           │   │ ← 交互式 Rating
│ └───────────────────────────────┘   │
│ ┌───────────────────────────────┐   │
│ │ 🎬 流浪地球 3                 │   │
│ │ ...(同样结构)                │   │
│ └───────────────────────────────┘   │
├─────────────────────────────────────┤
│ [✓ 评分成功](Toast,2秒后消失)     │
└─────────────────────────────────────┘

在这里插入图片描述

四、Rating 组件的视觉规格

4.1 默认星星样式

系统默认的 Rating 星星使用以下视觉方案:

  • 未选中星:灰色空心五角星(#E0E0E0 左右)
  • 选中星:金黄色实心五角星(#FFC107 左右)
  • 半星:左半黄色实心 + 右半灰色空心

这个默认样式与 Material Design 和 iOS 的评分组件视觉一致——用户无需学习就能理解含义。

4.2 尺寸与间距

星星的默认尺寸由组件的 widthheight 属性决定。如果 widthheight 未显式设置,Rating 使用默认尺寸(约 24vp × 24vp 的单星大小)。

在实践中,推荐显式设置 widthheight

  • 只读模式.width(120).height(22) —— 紧凑,适合信息展示区
  • 交互模式.width(160).height(30) —— 宽松,提供更大的触控目标

5 颗星之间的间距由组件自动计算(总宽度除以星数),开发者不需要手动设置间距。

4.3 自定义星星图标

starStyle 的三个 URI 参数允许替换默认的五角星:

.starStyle({
  backgroundUri: 'app.media.empty_star',    // 资源目录中的空星图片
  foregroundUri: 'app.media.filled_star',   // 资源目录中的满星图片
  secondaryUri: 'app.media.half_star'       // 半星图片(仅在 stepSize=0.5 时显示)
})

URI 格式支持:

  • app.media.xxx:应用资源目录(resources/base/media/)中的图片
  • http(s)://...:网络图片(需申请网络权限)
  • 空字符串 '':使用系统默认样式

在实际项目中,自定义星星图标最常见的场景是品牌定制——例如一家旅游 App 可能想用"棕榈树"图标替代星星,一家美食 App 可能想用"叉子"图标。starStyle 使得这种定制变得简单——只需替换三张图,不需要修改 Rating 的任何逻辑代码。

五、Rating 的最佳实践

5.1 何时使用 indicator 模式

indicator: true 适用于展示第三方数据的场景:

  • 电商平台的商品评分(4.7 分,基于 2.3 万条评价)
  • App Store 的应用评分
  • 餐厅/酒店的平均评分
  • 历史评分记录(用户之前给过的评分)

这些场景的共同特征是:评分数据来自外部(数据库/API),用户只能看,不能改。使用 indicator 模式可以防止用户误触改变评分,同时保持视觉一致性。

5.2 何时使用 stepSize(0.5)

半星精度(stepSize: 0.5)适用于信息密集型展示

  • 展示精确到一位小数的平均分(如 4.2、3.8)
  • 数据可视化面板
  • 对比图表

半星不应该用于用户交互式评分——让用户在 0-5 的 11 个选项(0, 0.5, 1, …, 5)中选择是过于精细的决策,增加了不必要的认知负担。交互式评分建议使用 stepSize(1)(6 个选项),简洁明了。

5.3 尺寸选择

使用场景 推荐 width 推荐 height 理由
只读展示(紧凑) 100-120 18-22 信息密度高,不占用过多空间
只读展示(突出) 140-180 24-28 强调评分数据(如商品详情页顶部)
交互式评分 150-200 28-36 需要更大的触控区域,减少误触

5.4 与文字标签的配合

Rating 组件本身不显示数字分数——它是纯粹的视觉表现。在实际应用中,Rating 通常与文字标签配合使用:

★★★★☆  4.2 分  (18.5 万评价)

三者形成完整的评分信息:

  • 视觉(Rating):快速传递"大约多少分"(一眼识别 4 星)
  • 数值(Text):精确传递"具体多少分"(4.2 这个数字)
  • 基数(Text):传递"有多少人打分"(18.5 万人,更具说服力)

在 Demo 中,这三者在一条 Row 中水平排列:Rating → 分数数字 → 评价人数。三者的文字颜色依次从醒目到柔化(橙色 → 灰色),形成视觉层级。

六、完整代码结构

RatingPage (~200 行)
├── 数据定义
│   └── MovieItem 接口 — 7 字段(含 avgRating 和 myRating)
├── 状态变量
│   ├── @State movies[4] — 4 部电影数据
│   └── @State showToast — Toast 显隐
├── 业务逻辑
│   └── rateMovie() — 不可变更新 myRating + Toast 弹出
├── 视图
│   ├── 标题栏 — ⭐ 影片评分
│   ├── 说明卡片 — Rating 组件介绍
│   ├── 4 张电影卡片(ForEach)
│   │   ├── 海报占位 + 电影信息
│   │   ├── 只读 Rating(豆瓣评分,stepSize=0.5)
│   │   └── 交互式 Rating(我的评分,stepSize=1 + onChange)
│   └── Toast 浮层(条件渲染 + Stack.position)
└── 生命周期
    └── aboutToAppear() — 初始化 4 部电影数据

七、总结

本文通过一个影片评分 Demo深入讲解了 HarmonyOS NEXT 中的 Rating 星级评分组件。Rating 将传统的手工绘制星星逻辑封装为标准组件,通过 indicator 开关区分只读和交互两种模式,通过 stepSize 控制评分精度,通过 starStyle 支持自定义图标样式。

核心要点回顾:

  1. Rating 的双模式indicator: true 创建只读展示(适用于社区评分、历史记录),indicator: false 创建交互式评分(适用于用户打分)。同一个组件的两个模式共享相同的视觉语言,但在交互行为上完全隔离。

  2. stepSize 控制精度stepSize(1) = 仅整星(快速选择,适用于用户打分),stepSize(0.5) = 半星精度(精确展示,适用于数据可视化)。两种精度服务于不同的业务场景,不应混用。

  3. starStyle 自定义图标:通过 backgroundUri(空星)、foregroundUri(满星)、secondaryUri(半星)三个 URI 参数,可以将默认的黄色五角星替换为任意自定义图标。这在品牌定制场景中非常实用。

  4. onChange 与状态管理:Rating 不维护内部评分状态——它始终反映外部传入的 rating 值。开发者需要在 onChange 回调中手动更新评分,并通过不可变数组模式触发 UI 刷新。这种"受控组件"模式保证了评分状态与业务数据的一致性。

  5. Rating 与文字的配合:视觉(星星)→ 数值(数字)→ 基数(评价人数)三者形成完整的评分信息链。视觉占比最大(Rating 组件的 120-200vp),数值用颜色强调(橙色/紫色),基数用浅色弱化(灰色 11sp)。

Rating 组件是 HarmonyOS NEXT 中"小而美"的典型代表——它的 API 只有 3 个方法 + 1 个事件,但通过参数组合可以覆盖从简单评分到复杂数据可视化的所有场景。这种"简单接口 + 灵活组合"的设计哲学,正是 ArkUI 声明式组件体系的核心优势。

Logo

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

更多推荐