鸿蒙新特性:Radio 单项选择组件——构建健康评估问卷

发布时间:2026/7/9 7:53:43
鸿蒙新特性:Radio 单项选择组件——构建健康评估问卷 单选是表单中最基础的交互。性别选择、支付方式、评分档位、问卷答案——所有这些多选一的场景都需要单选按钮。Radio 组件通过互斥的圆形按钮和清晰的选中标记让用户在多个互斥选项中做出明确的单一选择。HarmonyOS NEXT ArkUI 提供了 Radio 组件——一个标准的单项选择控件通常与group属性配合使用实现组内互斥。本文将深入讲解 Radio 组件与 Radio 组的 API并构建一个健康评估问卷——支持 5 道单选题、自动评分、健康等级分级和重新评估。关键词HarmonyOS、ArkUI、Radio、单项选择、问卷调查、健康评估、自动评分一、Radio 组件 API1.1 基本用法Radio({value:0,group:question1}).checked(this.selectedOption0).width(24).height(24).radioStyle({checkedBackgroundColor:#1677FF})核心参数与属性参数/属性类型说明valuestring该选项的值标识groupstring组名同组 Radio 互斥.checked()boolean是否选中State驱动.radioStyle()RadioStyle自定义选中状态的样式.width()/.height()Length按钮尺寸1.2 group 互斥机制Radio 的互斥通过group属性实现——所有group值相同的 Radio 自动互斥用户选择其中一个时同组其他 Radio 自动取消选中// 问题 1 的 4 个选项——所有 group 都是 question1Radio({value:0,group:question1})// 选项 ARadio({value:1,group:question1})// 选项 BRadio({value:2,group:question1})// 选项 CRadio({value:3,group:question1})// 选项 D// 问题 2 的 4 个选项——所有 group 都是 question2Radio({value:0,group:question2})// 选项 ARadio({value:1,group:question2})// 选项 B// ...问题 1 和问题 2 的 Radio 使用不同的group值因此互不影响。用户可以在问题 1 选 A、在问题 2 选 C——两者互不干扰。Demo 中通过q.concat(qIdx.toString())动态生成组名例如问题 0 的组名为q0问题 1 的组名为q1以此类推。1.3 checked 与 State 联动Radio 的checked属性需要手动绑定State变量来控制选中状态Radio({value:0,group:question1}).checked(this.answers[0]0)这里this.answers[0]存储问题 1 的选中选项索引-1表示未选0/1/2/3表示已选。当answers[0] 0时第一个 Radio 显示选中状态当用户点击其他 Radio 时answers[0]更新为新索引之前的 Radio 自动取消选中。这种用State数组管理所有问题答案的模式让 5 道题的答案统一存储、统一管理、统一重置。1.4 radioStyle 自定义样式.radioStyle({checkedBackgroundColor:#1677FF})checkedBackgroundColor控制选中时内圆点的填充颜色。默认的灰色选中圆点可能不够醒目自定义为蓝色后与页面主题色一致选中状态更清晰。1.5 行级点击区域Radio 按钮本身只有 24×24 的点击区域在移动端不够大。Demo 中将整个选项行设置为可点击Row(){Radio({value:...}).width(24).height(24)Text(option.label)}.onClick((){this.selectAnswer(qIdx,oIdx);})用户点击选项行的任意位置包括 Radio 和文字都会触发选择而不仅仅是点击 Radio 小圆圈。这显著提升了移动端的操作体验。1.6 选中行的视觉反馈选中行使用浅蓝背景#F0F5FF未选中行使用浅灰背景#F8F9FA选中文字更深更粗.fontColor(this.answers[qIdx]oIdx?#1a1a2e:#888899).fontWeight(this.answers[qIdx]oIdx?FontWeight.Medium:FontWeight.Normal).backgroundColor(this.answers[qIdx]oIdx?#F0F5FF:#F8F9FA)这种整行高亮的设计让用户一眼就能看到每道题的当前选择无需寻找那个小小的 Radio 按钮。二、健康评估问卷的整体设计2.1 页面架构SurveyPage ├── 标题栏 — 健康评估 进度计数已答/总题数 ├── 答题模式submitted false │ ├── 问题 1: 睡眠时长 — 4 个 Radio 选项 │ ├── 问题 2: 运动频率 — 4 个 Radio 选项 │ ├── 问题 3: 饮水量 — 4 个 Radio 选项 │ ├── 问题 4: 压力感受 — 4 个 Radio 选项 │ ├── 问题 5: ️ 饮食习惯 — 4 个 Radio 选项 │ └── 提交按钮全部完成时激活 └── 结果模式submitted true ├── 健康等级 emoji 标签 总分 ├── 健康建议文字 └── 重新评估按钮2.2 数据结构classQuestionOption{label:string;// 选项文字score:number;// 该选项的分值1-4}classQuestion{id:number;title:string;// 问题文字icon:string;// 图标 emojioptions:QuestionOption[];// 4 个选项}5 个问题覆盖了健康评估的核心维度问题图标4 个选项的分值睡眠时长不足5h(1) / 5-7h(2) / 7-8h(3) / 8h(4)运动频率几乎不(1) / 1-2次(2) / 3-4次(3) / 5次(4)饮水量不足3杯(1) / 3-5杯(2) / 6-8杯(3) / 8杯(4)压力感受很大(1) / 较大(2) / 一般(3) / 轻松(4)饮食习惯️偏油腻(1) / 偏清淡(2) / 均衡(3) / 规划(4)每题 4 个选项分值从 1 到 4总分范围 5-20。分值越高代表生活习惯越好。2.3 答案存储Stateanswers:number[][-1,-1,-1,-1,-1];5 个元素的数组-1表示未选0/1/2/3表示选中的选项索引。用户每点击一个选项selectAnswer通过slice()创建新数组并更新对应索引selectAnswer(questionIdx:number,optionIdx:number):void{letnewAnswersthis.answers.slice();newAnswers[questionIdx]optionIdx;this.answersnewAnswers;}注意这里使用了let newAnswers this.answers.slice()在方法内部而非 UI 函数中这符合 ArkTS 的语法规则。三、评分与结果3.1 总分计算getTotalScore():number{letscore0;for(leti0;ithis.answers.length;i){letidxthis.answers[i];if(idx0){scorethis.getQuestions()[i].options[idx].score;}}returnscore;}遍历所有已答问题累加各选项的分值。getQuestions()[i].options[idx].score通过问题索引和选项索引两级查找获取分值——这种设计让分值始终与选项绑定修改选项时只需改一处。3.2 健康等级评定getHealthLevel():HealthLevel{letscorethis.getTotalScore();if(score18)returnnewHealthLevel(非常健康,#52C41A,...,);if(score14)returnnewHealthLevel(比较健康,#1677FF,...,);if(score10)returnnewHealthLevel(需要关注,#FAAD14,...,⚠️);returnnewHealthLevel(急需调整,#FF4D4F,...,❗);}HealthLevel是一个专门的类而非匿名对象——ArkTS 要求所有对象字面量对应显式声明的类型包含 4 个字段字段说明label等级名称color主题色绿/蓝/金/红desc个性化疗建议emoji等级图标四个等级的颜色映射绿色18-20 分非常健康——积极完成蓝色14-17 分比较健康——肯定鼓励金色10-13 分需要关注——温和警示红色5-9 分急需调整——强烈提醒3.3 结果卡片提交后页面从答题模式切换为结果模式——问题列表隐藏取而代之的是一个结果卡片大号 emoji48px健康等级名称24px等级主题色总分显示“总分: 16 / 20”健康建议文字13px灰色重新评估按钮等级主题色圆角3.4 重新评估retakeSurvey():void{this.answers[-1,-1,-1,-1,-1];this.submittedfalse;}将答案重置为全-1未选状态submitted切回false。页面回到答题模式所有 Radio 恢复未选中状态提交按钮恢复禁用状态。四、提交控制4.1 完成度检测isComplete():boolean{for(leti0;ithis.answers.length;i){if(this.answers[i]-1)returnfalse;}returntrue;}当所有 5 题都已选择选项answers中无-1时isComplete()返回true。提交按钮根据此状态变换样式和行为Text(this.isComplete()?提交评估:请完成所有题目后提交).fontColor(this.isComplete()?#FFFFFF:#BBBBCC)// 背景色变化.backgroundColor(this.isComplete()?#1677FF:#F8F9FA)// 点击事件守卫.onClick((){if(this.isComplete()){this.submitSurvey();}})未完成时灰色文字 浅灰背景 点击无效。完成后白色文字 蓝色背景 可点击提交。4.2 进度计数标题栏右侧显示已答 / 总题数计数Text(this.getAnswerCount().toString().concat(/).concat(this.getQuestions().length.toString()))getAnswerCount():number{letcount0;for(leti0;ithis.answers.length;i){if(this.answers[i]!-1)count;}returncount;}随着用户逐题作答计数从 “0/5” 递增到 “5/5”给用户清晰的任务完成感。五、页面状态切换Demo 包含两种页面状态由submitted控制答题模式submitted false显示 5 个问题卡片 提交按钮结果模式submitted true显示结果卡片问题列表隐藏两种状态共用同一个Scroll容器通过if (this.submitted)和if (!this.submitted)条件渲染切换。切换时页面滚动位置自然回到顶部因为内容完全替换用户看到结果卡片位于屏幕上方。六、交互流程演示6.1 开始答题进入页面5 道题的所有选项均为未选中状态。标题栏显示0/5。提交按钮显示请完成所有题目后提交灰底灰字不可点击。6.2 逐题作答点击第 1 题睡眠时长的第 3 个选项7-8 小时。该选项行变为浅蓝背景Radio 内圆点变为蓝色文字变深加粗。标题栏计数变为1/5。依次完成其余 4 题。标题栏从2/5递增到5/5。完成第 5 题后提交按钮变为蓝底白字提交评估提示用户可以提交。6.3 查看结果点击提交评估。Toast 提示评估完成查看结果。页面切换为结果模式——结果卡片显示健康等级、总分和个性化建议。重新评估按钮位于卡片底部。6.4 重新评估点击重新评估。页面回到答题模式所有选项恢复未选中。标题栏计数归零0/5提交按钮恢复灰色禁用状态。用户可以修改选择并重新提交。七、总结本文通过健康评估问卷这个实战案例全面讲解了 ArkUI Radio 单项选择组件的使用方法。核心知识点包括Radio 基础 APIvaluegroup组内互斥 .checked()状态绑定选项行交互设计整行点击 选中高亮背景 文字颜色/粗细变化答案管理State数组统一存储 slice()不可变更新自动评分选项分值绑定 总分累加 四级健康等级判定完成度控制isComplete()检测 按钮样式/行为条件切换双状态切换答题模式 vs 结果模式 重新评估重置对象字面量约束返回值类型必须使用显式声明的 classHealthLevel单选是移动表单的基础组件。一个好的单选体验不仅仅是能点一个圆——它需要清晰的选中视觉反馈、足够的点击热区、组间独立互不干扰的互斥逻辑和流畅的答案管理。ArkUI 的 Radio 组件提供了简洁的valuegroupAPI让开发者将注意力集中在问题的组织、答案的存储和评分的计算上。