鸿蒙新特性——Rating 星级评分组件详解
一、引言
星级评分是移动端应用中最常见的交互组件之一。从 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 |
初始评分值,范围 0 到 stars(默认 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
交互式评分区分于只读展示的三个设计要点:
- 更大:160vp vs 120vp,为手指点击提供足够的触控面积
- 更高:30vp vs 22vp,避免星星太矮导致误触
- 更反馈:右侧文字实时显示"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 通过 Stack 的 position({ 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 尺寸与间距
星星的默认尺寸由组件的 width 和 height 属性决定。如果 width 和 height 未显式设置,Rating 使用默认尺寸(约 24vp × 24vp 的单星大小)。
在实践中,推荐显式设置 width 和 height:
- 只读模式:
.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 支持自定义图标样式。
核心要点回顾:
-
Rating 的双模式:
indicator: true创建只读展示(适用于社区评分、历史记录),indicator: false创建交互式评分(适用于用户打分)。同一个组件的两个模式共享相同的视觉语言,但在交互行为上完全隔离。 -
stepSize 控制精度:
stepSize(1)= 仅整星(快速选择,适用于用户打分),stepSize(0.5)= 半星精度(精确展示,适用于数据可视化)。两种精度服务于不同的业务场景,不应混用。 -
starStyle 自定义图标:通过
backgroundUri(空星)、foregroundUri(满星)、secondaryUri(半星)三个 URI 参数,可以将默认的黄色五角星替换为任意自定义图标。这在品牌定制场景中非常实用。 -
onChange 与状态管理:Rating 不维护内部评分状态——它始终反映外部传入的
rating值。开发者需要在onChange回调中手动更新评分,并通过不可变数组模式触发 UI 刷新。这种"受控组件"模式保证了评分状态与业务数据的一致性。 -
Rating 与文字的配合:视觉(星星)→ 数值(数字)→ 基数(评价人数)三者形成完整的评分信息链。视觉占比最大(Rating 组件的 120-200vp),数值用颜色强调(橙色/紫色),基数用浅色弱化(灰色 11sp)。
Rating 组件是 HarmonyOS NEXT 中"小而美"的典型代表——它的 API 只有 3 个方法 + 1 个事件,但通过参数组合可以覆盖从简单评分到复杂数据可视化的所有场景。这种"简单接口 + 灵活组合"的设计哲学,正是 ArkUI 声明式组件体系的核心优势。
更多推荐




所有评论(0)