鸿蒙新特性——Toggle 开关组件详解
一、引言
开关(Toggle)是移动端设置页面中最常见的交互组件。通知开关、隐私权限、夜间模式、自动播放——几乎所有"开/关"二元选择都通过 Toggle 实现。不同的使用场景需要不同的开关形态:设置列表中的滑动开关、多选项中的勾选框、工具栏中的切换按钮。
在传统开发中,这三种形态通常由三个不同的组件实现(UISwitch + Checkbox + SegmentedControl),各有各的 API,学习成本高。而 HarmonyOS 通过 Toggle 组件统一了这三种形态——通过 ToggleType 枚举,同一个组件可以呈现为 Switch(滑动开关)、Checkbox(复选框)或 Button(切换按钮),API 高度一致,只需改变一个参数即可切换形态。
本文通过一个通知设置 Demo 深入讲解 Toggle 组件的三种类型:Switch 的主从开关联动模式?Checkbox 的多选计数?Button 的切换按钮?以及 enabled 属性的禁用控制。
阅读完本文,你将能够:
- 使用 Toggle 组件的三种类型(Switch/Checkbox/Button)
- 实现主开关 + 子开关的联动禁用模式
- 实现 Checkbox 多选计数
- 使用
enabled属性控制 Toggle 的可用状态 - 构建完整的通知设置功能
二、Toggle 组件 API 总览
2.1 构造函数
Toggle(options: ToggleOptions)
interface ToggleOptions {
type: ToggleType; // 开关类型
isOn?: boolean; // 初始开关状态
}
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
type |
ToggleType | 必填 | 三种类型:Switch/Checkbox/Button |
isOn |
boolean | false | 初始开关状态,true = 开 |
2.2 ToggleType 三种类型
enum ToggleType {
Switch, // 滑动开关——圆形滑块左右滑动
Checkbox, // 复选框——方形勾选框
Button // 切换按钮——矩形按钮,按下=开
}
| 类型 | 外观 | 典型场景 |
|---|---|---|
Switch |
椭圆形轨道 + 圆形滑块,滑动切换 | 设置列表开关(WiFi、蓝牙、通知) |
Checkbox |
方形框,勾选显示对勾 | 多选项、协议同意、批量选择 |
Button |
矩形按钮,按下态/未按下态 | 工具栏切换(粗体/斜体)、筛选按钮 |
2.3 链式方法
// 激活态颜色
.selectedColor(value: ResourceColor): ToggleAttribute
// Switch 的滑块颜色
.switchPointColor(value: ResourceColor): ToggleAttribute
// 状态变化回调
.onChange(callback: Callback<boolean>): ToggleAttribute
// 是否可用(禁用态)
.enabled(value: boolean): ToggleAttribute
| 方法 | 说明 |
|---|---|
.selectedColor(ResourceColor) |
开关激活时的轨道/勾选颜色 |
.switchPointColor(ResourceColor) |
Switch 类型滑块的颜色(仅 Switch 生效) |
.onChange(Callback<boolean>) |
用户切换开关时的回调,参数为 true/false |
.enabled(boolean) |
是否可操作,false 时组件变灰且不可点击 |
2.4 Toggle vs 自建开关方案
| 特性 | Toggle 组件 | 自建方案 |
|---|---|---|
| Switch 滑动开关 | type: ToggleType.Switch 一行搞定 |
动画 + 手势 + 状态管理 |
| Checkbox 复选框 | type: ToggleType.Checkbox 一行搞定 |
Image 切换 + 状态管理 |
| Button 切换按钮 | type: ToggleType.Button 一行搞定 |
Button 样式切换 |
| 三种类型 API 统一 | 换一个 type 参数即可 | 三种组件各自实现 |
| 禁用态 | .enabled(false) 即可 |
需手动处理颜色和交互 |
Toggle 组件统一了 ArkUI 中所有的二元开关场景。在任何需要 true/false 二元选择的地方,Toggle 都是最优选择。
三、Demo 设计:通知设置
3.1 功能概述
Demo 是一个通知设置页面,模拟手机系统的通知管理:
- 通知总开关:Switch 类型的主开关,控制所有子设置项的启用/禁用
- 子设置项(4 个 Switch):消息推送、声音提醒、振动提醒、角标显示——每个都有独立的开关
- 通知渠道(3 个 Checkbox):推送通知、短信通知、邮件通知——多选模式,底部显示已选数量
- 勿扰模式:Button 类型的切换按钮
- 状态计数:总开关卡片显示"X / 4 项"已启用
- 恢复默认:一键将所有设置重置为初始值
3.2 交互点
| # | 交互 | 说明 |
|---|---|---|
| 1 | 主开关联动 | 关闭主开关 → 所有子开关禁用且强制关闭 |
| 2 | 子开关独立切换 | 主开关开启时,每个子开关独立控制 |
| 3 | Checkbox 多选 | 勾选/取消勾选通知渠道,底部计数实时更新 |
| 4 | 恢复默认 | 一键重置所有开关到默认状态 |
![]() |
四、完整代码实现
4.1 状态变量
// 主开关
@State masterOn: boolean = true;
// 子开关(Switch 类型)
@State msgEnabled: boolean = true;
@State soundEnabled: boolean = true;
@State vibrateEnabled: boolean = false;
@State badgeEnabled: boolean = true;
// 通知渠道(Checkbox 类型)
@State channelPush: boolean = true;
@State channelSms: boolean = true;
@State channelEmail: boolean = false;
4.2 主开关联动逻辑
toggleMaster(value: boolean) {
this.masterOn = value;
this.msgEnabled = value;
this.soundEnabled = value;
this.vibrateEnabled = value;
this.badgeEnabled = value;
}
当用户切换主开关时,所有四个子开关跟随主开关的值。关闭主开关时,所有子项强制关闭(false);开启主开关时,所有子项恢复开启(true)。
在 UI 渲染中,子开关的 isOn 值根据 masterOn 计算:
Toggle({ type: ToggleType.Switch, isOn: this.masterOn ? this.msgEnabled : false })
.enabled(this.masterOn)
- 当
masterOn === true:isOn= 子开关的真实值(用户单独切换的值),开关可点击 - 当
masterOn === false:isOn=false(强制显示为关闭状态),开关不可点击(enabled(false))
这种双重控制模式确保:
- 主关时所有子项 UI 显示为关闭(视觉一致)
- 主关时所有子项 Toggle 不可点击(交互禁用)
- 主开时各子项恢复各自独立状态(状态保留)
4.3 子开关配置(Switch 类型)
Toggle({ type: ToggleType.Switch, isOn: this.masterOn ? this.msgEnabled : false })
.selectedColor('#1677FF')
.enabled(this.masterOn)
.onChange((value: boolean) => { this.msgEnabled = value; })
.selectedColor('#1677FF'):激活时轨道颜色为蓝色.enabled(this.masterOn):动态绑定禁用态——主开关关闭时 Toggle 灰显且不可点击.onChange():只在主开关开启时才会被触发(disabled 状态下不触发)
4.4 通知渠道配置(Checkbox 类型)
Toggle({ type: ToggleType.Checkbox, isOn: this.channelPush })
.selectedColor('#1677FF')
.onChange((value: boolean) => { this.channelPush = value; })
Checkbox 与 Switch 的区别:
- 外观:方形框 + 对勾 vs 椭圆轨道 + 圆形滑块
- 语义:多选勾选 vs 单一开关
- 适用场景:多项并行选择 vs 单项二元开关
底部显示计数:
get channelCount(): number {
let count = 0;
if (this.channelPush) count++;
if (this.channelSms) count++;
if (this.channelEmail) count++;
return count;
}
4.5 Toggle 类型的 Button 模式
Toggle({ type: ToggleType.Button, isOn: false })
.selectedColor('#1677FF')
Button 类型将 Toggle 渲染为矩形按钮——按下时显示激活色,弹起时恢复默认。适合工具栏中的切换按钮(如文本编辑器的粗体/斜体切换)。
4.6 恢复默认设置
resetDefaults() {
this.masterOn = true;
this.msgEnabled = true;
this.soundEnabled = true;
this.vibrateEnabled = false;
this.badgeEnabled = true;
this.channelPush = true;
this.channelSms = true;
this.channelEmail = false;
}
一键恢复所有 @State 变量到初始值。由于所有 Toggle 的 isOn 都绑定到这些 @State 变量,重置后 UI 自动同步更新。
五、关键技术点详解
5.1 enabled 属性的双重作用
.enabled(false) 同时产生两个效果:
- 视觉禁用:Toggle 变灰(降低透明度或改变颜色),用户一看就知道不可操作
- 交互禁用:点击无反应,
.onChange()不触发
在 Demo 中,.enabled(this.masterOn) 动态绑定,实现了"主开关 → 子开关"的级联控制。这是设置页面中非常常见的交互模式(如关闭 WiFi → 所有 WiFi 相关设置灰显不可点)。
5.2 isOn 与 onChange 的绑定陷阱
常见的错误写法:
// ❌ 错误:忘记更新 @State 变量
Toggle({ type: ToggleType.Switch, isOn: this.msgEnabled })
.onChange((value: boolean) => {
// 空的!什么都没做
})
// 结果:Toggle 看起来能切换,但 isOn 没更新,重新渲染后恢复原状
正确的写法必须在 onChange 中更新绑定的 @State 变量:
// ✅ 正确
Toggle({ type: ToggleType.Switch, isOn: this.msgEnabled })
.onChange((value: boolean) => {
this.msgEnabled = value; // 必须更新!
})
5.3 三种类型的 API 差异
三种类型共用同一个 Toggle 构造函数,但支持不同的样式属性:
| 属性 | Switch | Checkbox | Button |
|---|---|---|---|
selectedColor |
✓ 轨道颜色 | ✓ 勾选颜色 | ✓ 激活背景色 |
switchPointColor |
✓ 滑块颜色 | ✗ 不适用 | ✗ 不适用 |
enabled |
✓ | ✓ | ✓ |
onChange |
✓ | ✓ | ✓ |
switchPointColor 仅对 Switch 类型生效,Change 和 Button 类型调用无效(不报错但不产生效果)。
5.4 计算属性 vs @State
// 使用 getter(推荐)
get enabledCount(): number {
return [this.msgEnabled, this.soundEnabled, this.vibrateEnabled, this.badgeEnabled]
.filter(Boolean).length;
}
// 使用 @State(冗余)
@State enabledCount: number = 4;
// 每次修改开关都要记得更新 enabledCount,容易遗漏
enabledCount 是一个派生值——它完全由其他 @State 变量的值决定,不需要独立的 @State 存储。使用 getter 计算属性既减少了状态量,又避免了忘记同步的问题。每次 UI 刷新时(任一开关变化触发),getter 自动重新计算。
5.5 Button 类型的文本定制
Toggle 的 Button 类型渲染为按钮,但按钮上的文字通过 .text() 方法设置:
Toggle({ type: ToggleType.Button, isOn: false })
.text('勿扰')
.selectedColor('#1677FF')
注意:.text() 是 Toggle Button 类型的特有方法,Switch 和 Checkbox 类型不支持。
六、运行效果
6.1 通知总开关
总开关卡片显示通知总开关(Switch 蓝色激活态),下方"已启用 3 / 4 项"计数。四个子开关中三个开启(消息推送、声音提醒、角标显示),振动提醒关闭。
6.2 主开关联动
点击总开关关闭——所有四个子开关的 Switch 滑块跳到左侧(关闭态),轨道变灰且不可点击。计数变为"已启用 0 / 4 项"(灰色)。
6.3 子开关独立操作
重新打开总开关——四个子开关恢复之前各自的状态(三个开一个关),计数恢复"3 / 4 项"。单独切换振动提醒为开启——计数变为"4 / 4 项"。
6.4 复选框多选
通知渠道区:推送通知和短信通知已勾选(蓝色对勾),邮件通知未勾选。底部显示"已选择 2 个渠道"。点击邮件通知的对勾——变为已选择 3 个。
6.5 恢复默认
点击"恢复默认设置"按钮——所有开关和复选框恢复到初始值(消息开启、声音开启、振动关闭、角标开启、推送勾选、短信勾选、邮件未选)。
七、最佳实践与注意事项
7.1 何时使用哪种类型
| 场景 | 推荐类型 | 原因 |
|---|---|---|
| 设置项开关(单选项) | Switch | 符合系统设置 UI 习惯 |
| 多选场景(可并行的选择) | Checkbox | 语义明确,可多选 |
| 工具栏中的状态切换 | Button | 节省空间,视觉简洁 |
| 协议/条款同意 | Checkbox | 法律语义——“我同意” |
| 即时生效的全局开关 | Switch | 即时反馈,手势友好 |
7.2 常见问题
Q: Toggle 可以设置默认开启状态吗?
A: 在构造函数中设置 isOn: true 或在初始化 @State 变量时赋值 true。
Q: 为什么关闭主开关后子开关的状态丢失了?
A: 关键是不直接修改子开关的 @State 变量,而是通过 enabled + 条件 isOn 实现"视觉关闭"而不"逻辑重置"。本 Demo 中的实现(isOn: this.masterOn ? this.msgEnabled : false)可以保留子开关的独立状态。
Q: Checkbox 和 Switch 可以放在同一个组里吗?
A: 可以。它们都是 Toggle 组件,只是类型不同。但出于 UX 一致性考虑,建议同一个功能区使用同一种类型。
八、总结
本文通过一个通知设置的实战 Demo,深入讲解了 HarmonyOS Toggle 开关组件的三种类型及核心用法:
- 三种类型:Switch(滑动开关)、Checkbox(复选框)、Button(切换按钮),通过
type参数切换 - 主开关联动:
.enabled()动态绑定 + 条件isOn实现级联禁用 - 状态计数:getter 计算属性实时统计启用数量
- 恢复默认:一键重置所有
@State变量到初始值
Toggle 是 ArkUI 二元开关的统一解决方案。从设置页面到权限管理,从多选表单到工具切换,Toggle 以其统一的 API 和三种灵活的呈现形态,覆盖了所有开/关交互场景。希望本文能帮助你在实际项目中高效运用 Toggle 组件。
本文基于 HarmonyOS NEXT API 24 编写,代码经 DevEco Studio 6.1.1 编译验证通过。
更多推荐




所有评论(0)