一、引言

开关(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 是一个通知设置页面,模拟手机系统的通知管理:

  1. 通知总开关:Switch 类型的主开关,控制所有子设置项的启用/禁用
  2. 子设置项(4 个 Switch):消息推送、声音提醒、振动提醒、角标显示——每个都有独立的开关
  3. 通知渠道(3 个 Checkbox):推送通知、短信通知、邮件通知——多选模式,底部显示已选数量
  4. 勿扰模式:Button 类型的切换按钮
  5. 状态计数:总开关卡片显示"X / 4 项"已启用
  6. 恢复默认:一键将所有设置重置为初始值

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 === trueisOn = 子开关的真实值(用户单独切换的值),开关可点击
  • masterOn === falseisOn = false(强制显示为关闭状态),开关不可点击(enabled(false)

这种双重控制模式确保:

  1. 主关时所有子项 UI 显示为关闭(视觉一致)
  2. 主关时所有子项 Toggle 不可点击(交互禁用)
  3. 主开时各子项恢复各自独立状态(状态保留)

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) 同时产生两个效果:

  1. 视觉禁用:Toggle 变灰(降低透明度或改变颜色),用户一看就知道不可操作
  2. 交互禁用:点击无反应,.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 开关组件的三种类型及核心用法:

  1. 三种类型:Switch(滑动开关)、Checkbox(复选框)、Button(切换按钮),通过 type 参数切换
  2. 主开关联动.enabled() 动态绑定 + 条件 isOn 实现级联禁用
  3. 状态计数:getter 计算属性实时统计启用数量
  4. 恢复默认:一键重置所有 @State 变量到初始值

Toggle 是 ArkUI 二元开关的统一解决方案。从设置页面到权限管理,从多选表单到工具切换,Toggle 以其统一的 API 和三种灵活的呈现形态,覆盖了所有开/关交互场景。希望本文能帮助你在实际项目中高效运用 Toggle 组件。


本文基于 HarmonyOS NEXT API 24 编写,代码经 DevEco Studio 6.1.1 编译验证通过。

Logo

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

更多推荐