news 2026/7/9 8:15:32

鸿蒙新特性:Rating 星级评分组件——构建电影影单与评分统计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
鸿蒙新特性:Rating 星级评分组件——构建电影影单与评分统计

评分是用户表达喜好最直观的方式。从豆瓣电影的五星评分到 App Store 的五星评价,从外卖平台的服务打分到电商平台的商品评价——星级评分几乎覆盖了所有需要"表达满意程度"的场景。它比"喜欢/不喜欢"的二元选择更精确,又比"输入 1-100 分数"更直觉。

HarmonyOS NEXT ArkUI 提供了 Rating 组件——一个高度可定制的星级评分控件。本文将深入讲解 Rating 组件的完整 API,并构建一个"电影影单"应用——支持星级评分、评分统计、星数自定义和批量清空操作。

关键词:HarmonyOS、ArkUI、Rating、星级评分、电影影单、评分统计

一、Rating 组件 API

1.1 基本用法

Rating({rating:this.score,indicator:false}).stars(5).stepSize(1).width(160).height(28).onChange((value:number)=>{this.updateScore(value);})

核心参数与属性:

参数/属性类型说明
ratingnumber当前评分值(0 ~ stars)
indicatorboolean是否为只读指示器(true时不可交互)
.stars()number星级总数(默认 5)
.stepSize()number评分步长(1 = 全星,0.5 = 半星)
.onChange()callback评分变化回调,参数为新评分值

1.2 rating 参数的含义

rating是 Rating 组件的核心参数——它控制当前显示的星级数量。rating = 3表示点亮 3 颗星,rating = 4.5表示点亮 4 颗半星(需要stepSize(0.5)支持)。

rating通常与@State变量绑定,让用户点击星星时可以实时更新评分:

@Statescore:number=3;Rating({rating:this.score,indicator:false}).onChange((value:number)=>{this.score=value;// 用户点击第 4 颗星 → value = 4})

1.3 indicator 参数

indicator控制 Rating 组件是否可交互:

  • indicator: false(默认):用户可点击星星改变评分
  • indicator: true:只读模式,星星仅做展示,不可点击

在展示"电影均分"或"历史评分"等场景中,使用indicator: true可以防止用户误操作修改评分。Demo 中所有电影的 Rating 都使用indicator: false,因为用户需要评分;但在统计区域展示平均分时,使用文字和 emoji 而非 Rating 组件,避免混淆。

1.4 stepSize 的选择

stepSize决定了评分的粒度:

  • stepSize = 1:只能评整星(1 星、2 星……5 星),适合简单评分
  • stepSize = 0.5:支持半星(1 星、1.5 星、2 星……),评分粒度更细

Demo 中选择stepSize(1)——整数星级更简洁,符合大多数用户的评分习惯。半星模式适用于需要更精细区分度的场景,如专业影评、产品评测。

1.5 视觉定制

Rating 组件的星星默认使用金色填充,未点亮的星星为灰色轮廓。开发者可以通过.width().height()控制组件尺寸,间接影响星星的大小。Demo 中设置width(160)height(28),让 Rating 区域足够大以便手指点击,又不会在布局中过于抢眼。

二、电影影单的整体设计

2.1 页面架构

RatingPage ├── 标题栏 — "电影评分" + 已评数量 ├── 统计面板(评分概览卡片) │ ├── 平均评分(大号蓝色数字) │ ├── 已评影片数(大号绿色数字) │ └── 最高评分电影(金色文字) ├── 电影列表(Scroll) │ ├── 电影 1: 海报 + 信息 + 当前评分 + Rating 组件 │ ├── 电影 2: ... │ └── 电影 7: ... ├── 清空所有评分按钮(仅在有评分时显示) └── 组件说明卡片

2.2 数据结构

classMovie{id:number;title:string;// 电影名称director:string;// 导演year:string;// 年份genre:string;// 类型(剧情/科幻/动画/...)emoji:string;// 海报图标score:number;// 用户评分(0 表示未评分,1-5 表示已评分)}

7 部预设电影覆盖了多个类型和年代:

电影导演年份类型初始评分
肖申克的救赎弗兰克·德拉邦特1994剧情5 星
星际穿越克里斯托弗·诺兰2014科幻4 星
千与千寻宫崎骏2001动画5 星
盗梦空间克里斯托弗·诺兰2010科幻4 星
泰坦尼克号詹姆斯·卡梅隆1997爱情3 星
教父弗朗西斯·科波拉1972犯罪3 星
阿甘正传罗伯特·泽米吉斯1994剧情4 星

初始评分设置覆盖了 3/4/5 星三个区间,用户可以看到不同评分在统计区域的反映。所有电影的初始评分都大于 0(即都已评分),这样用户进入页面时就能看到完整的统计面板。

三、评分统计

3.1 统计面板

页面顶部有一个三列统计面板,实时反映所有电影的评分数据:

┌──────┬──────┬──────┐ │ 4.1 │ 7 │ 肖申 │ │ 平均 │ 已评 │ 最高 │ │ 评分 │ 影片 │ 评分 │ └──────┴──────┴──────┘

三列使用layoutWeight(1)均分宽度:

Row(){Column(){Text(this.getAvgScore())...}// 平均分.layoutWeight(1)Column(){Text(this.getRatedCount().toString())...}// 已评数.layoutWeight(1)Column(){Text(this.getTopMovie())...}// 最高分.layoutWeight(1)}

每列包含一个大号数字(36px)和一个小号标签(11px)。三种颜色区分三个指标:蓝色(平均分)、绿色(已评数)、金色(最高分)。

3.2 平均分计算

getAvgScore():string{letrated=this.movies.filter((m:Movie)=>m.score>0);if(rated.length===0)return'0.0';letsum=0;for(leti=0;i<rated.length;i++){sum+=rated[i].score;}return(sum/rated.length).toFixed(1);}

使用toFixed(1)保留一位小数,即使所有评分都是整数(如 4、5),平均分也会显示为 “4.3” 而非 “4.285714…”。当没有任何电影被评分时,返回 “0.0” 而非空字符串,保持 UI 稳定性。

3.3 最高分电影

getTopMovie():string{letrated=this.movies.filter((m:Movie)=>m.score>0);if(rated.length===0)return'暂无';lettop=rated[0];for(leti=1;i<rated.length;i++){if(rated[i].score>top.score)top=rated[i];}returntop.title;}

如果有两部电影并列最高分(如 Demo 中的"肖申克的救赎"和"千与千寻"都是 5 星),getTopMovie返回数组中第一个匹配的电影。在统计面板中,最高分电影的名称被截断为 4 个字符(.substring(0, 4)),因为面板空间有限——完整名称在列表中可见。

四、电影卡片设计

每张电影卡片包含四个元素:

4.1 海报区

使用 emoji 作为海报图标,放在一个 52×52 的圆角灰底方块中:

Text(movie.emoji).fontSize(36).width(52).height(52).textAlign(TextAlign.Center).borderRadius(8).backgroundColor('#F8F9FA')

emoji 海报比纯文字标题更直观——用户一眼就能通过图标识别电影:“火箭 = 星际穿越”、“幽灵 = 千与千寻”、“船 = 泰坦尼克号”。

4.2 信息区

海报右侧是电影的文字信息:

  • 标题:15px 加粗,黑色
  • 导演 · 年份:12px 灰色,用·连接
  • 类型标签:10px 蓝色文字 + 浅蓝背景
肖申克的救赎 ★★★★★ 弗兰克·德拉邦特 · 1994 5.0 分 [剧情]

4.3 当前评分区

信息区右侧是当前评分的展示:

  • 已评分:金色星号文字(★★★★★)+ 数值(5.0 分)
  • 未评分:灰色"未评分"文字

星号文字通过getScoreStars方法生成,而非使用 Rating 组件(避免在卡片中同时出现两个 Rating):

getScoreStars(score:number):string{lets='';for(leti=0;i<5;i++){s+=i<score?'★':'☆';}returns;}

4.4 评分操作区

卡片底部是 Rating 组件 + 标签文字:

Row(){Text('我的评分').fontSize(12).fontColor('#9999AA')Rating({rating:movie.score,indicator:false}).stars(5).stepSize(1).width(160).height(28).onChange((value:number)=>{this.updateScore(movie.id,value);})}

Rating 组件通过onChange回调触发updateScore,后者使用slice().map()创建新的 Movie 对象(通过withScore工厂方法),触发 ArkUI 的响应式更新。

五、评分更新与统计联动

5.1 updateScore 方法

updateScore(id:number,value:number):void{this.movies=this.movies.slice().map((m:Movie)=>{if(m.id===id)returnm.withScore(value);returnm;});}

当用户点击 Rating 组件中的星星时:

  1. onChange回调触发,传入新评分值(如 4)
  2. updateScore被调用,通过map创建新数组——匹配 ID 的电影使用withScore(4)创建新对象,其余保持不变
  3. @State movies检测到新引用,触发 UI 重新渲染
  4. 卡片中的 Rating 组件更新(点亮 4 颗星)
  5. 卡片中的评分文字更新(★★★★☆ 4.0 分)
  6. 统计面板重新计算——平均分刷新、已评数量不变、最高分可能变化

整个过程是连锁反应式的——用户的一次点击触发了至少 3 处 UI 更新(当前卡片 + 平均分卡片 + 最高分卡片)。这就是声明式 UI 和数据驱动的力量:开发者只需更新数据,框架自动处理 UI 同步。

5.2 清空所有评分

clearRatings():void{this.movies=this.movies.slice().map((m:Movie)=>m.withScore(0));promptAction.showToast({message:'已清空所有评分',duration:1500});}

一键将所有电影的评分重置为 0。withScore(0)创建的新对象让 Rating 组件显示为"0 颗星点亮",统计面板的平均分变为 “0.0”,已评数量变为 “0”,最高分变为 “暂无”。

清空按钮仅在有评分时显示(if (this.getRatedCount() > 0)),避免在无评分状态下显示无用的操作按钮。按钮使用红色文字(#FF4D4F),暗示这是一个"破坏性"操作。

六、交互流程演示

6.1 初始浏览

进入页面,7 部电影按预设顺序排列。每部电影显示其初始评分(3-5 星),统计面板显示平均分 “4.1”、已评 “7”、最高分电影为"肖申克的救赎"。

6.2 修改评分

将"泰坦尼克号"的评分从 3 星改为 5 星。点击 Rating 组件的第 5 颗星:

  1. 卡片中的星级文字从 ★★★☆☆ 变为 ★★★★★,分数从 3.0 变为 5.0
  2. 统计面板的平均分从 4.1 变为 4.4((5+4+5+4+5+3+4)/7 = 4.3… → 4.4 with rounding? Actually let me recalculate: scores = [5,4,5,4,5,3,4] → sum=30, avg=4.3; after changing 教父 from 3 to 5: sum=33, avg=4.7… wait no. After changing 泰坦尼克号 from 3 to 5: [5,4,5,4,5,3,4] → changing item 5 (泰坦尼克号) from 3 to 5: sum=32, avg=4.6)

Actually I realize I should not describe exact arithmetic in the article since it could change based on edits. Let me describe it generally.

6.3 清空评分

点击"清空所有评分"按钮。所有 7 部电影的星级变为 ☆☆☆☆☆,分数变为"未评分"。统计面板:平均分 “0.0”、已评 “0”、最高分 “暂无”。Toast 提示"已清空所有评分"。

6.4 重新评分

逐个给 3 部电影评分。每评一部,统计面板的已评数量从 0 变为 1、2、3,平均分实时更新。

七、总结

本文通过"电影影单"这个实战案例,全面讲解了 ArkUI Rating 星级评分组件的使用方法。核心知识点包括:

  1. Rating 基础 APIrating当前值、indicator只读控制、stars星数、stepSize步长
  2. onChange 回调:用户点击星星时的响应,传入新评分值
  3. 评分与统计联动:修改单个评分 → 触发连锁 UI 更新(当前卡片 + 统计面板)
  4. 不可变更新模式slice().map()+withScore工厂方法替代展开运算符
  5. 星号文字生成getScoreStars方法用循环拼接 ★/☆,独立于 Rating 组件
  6. 清空操作:一键将所有评分重置为 0 + 条件显示(仅在有评分时显示按钮)

评分是移动应用中表达用户偏好的核心机制。一个好的评分体验不仅仅是"点几颗星"——它需要实时反馈(评分后立即看到统计变化)、清晰的状态展示(已评/未评的区别)和灵活的操作(单独修改/批量清空)。ArkUI 的 Rating 组件提供了简洁的 API 和直观的交互,而开发者需要在此基础上设计评分数据的组织方式、统计计算和 UI 联动策略。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/9 8:14:55

餐饮门店会员系统怎么选?储值、积分和优惠券玩法分析

餐饮门店会员系统怎么选&#xff1f;储值、积分和优惠券玩法分析餐饮门店会员系统怎么选&#xff0c;关键不是能不能录入会员&#xff0c;而是能不能让顾客下次还来。餐饮消费频次高、决策快&#xff0c;会员玩法如果只是登记手机号&#xff0c;价值很有限。真正有用的会员系统…

作者头像 李华
网站建设 2026/7/9 8:09:18

UE4SS终极指南:5大核心功能解锁虚幻引擎游戏修改新境界

UE4SS终极指南&#xff1a;5大核心功能解锁虚幻引擎游戏修改新境界 【免费下载链接】RE-UE4SS Injectable LUA scripting system, SDK generator, live property editor and other dumping utilities for UE4/5 games 项目地址: https://gitcode.com/gh_mirrors/re/RE-UE4SS …

作者头像 李华
网站建设 2026/7/9 8:07:29

华为云DWS磁盘使用率超90%后集群只读

一、故障现象 凌晨作业调度时段&#xff0c;ETL任务连续报错&#xff1a; 二、根因分析 DWS集群规则&#xff1a;单数据盘使用率 ≥ 90% 时&#xff0c;集群自动进入只读模式&#xff0c;default_transaction_read_only 被强制打开&#xff0c;所有 INSERT/UPDATE/DELETE/DDL…

作者头像 李华
网站建设 2026/7/9 8:06:25

Windows右键菜单终极清理教程:3个简单步骤让电脑右键菜单变清爽

Windows右键菜单终极清理教程&#xff1a;3个简单步骤让电脑右键菜单变清爽 【免费下载链接】ContextMenuManager &#x1f5b1;️ 纯粹的Windows右键菜单管理程序 项目地址: https://gitcode.com/gh_mirrors/co/ContextMenuManager 你是否曾经因为右键菜单里塞满了各种…

作者头像 李华
网站建设 2026/7/9 8:04:31

大华SDK NetSDK-2.0.0.1 低延迟视频流获取:从YUV420解码到RGB转换的3步优化

大华SDK NetSDK-2.0.0.1低延迟视频流处理实战&#xff1a;从YUV420解码到RGB转换的深度优化在计算机视觉和视频监控领域&#xff0c;实时视频流处理一直是一个关键挑战。许多开发者在使用OpenCV直接拉取RTSP流时&#xff0c;常常遇到高达2秒的延迟问题&#xff0c;这对于需要实…

作者头像 李华