鸿蒙新特性——Toggle 开关组件详解
一、引言
开关(Toggle)是移动端设置页面中最基础的交互元素。从 iOS 设置中的 Wi-Fi 开关到 Android 通知栏的蓝牙图标,从 App 的深色模式切换到隐私设置的定位授权——一个简单的开/关二元选择,承载了用户对应用行为的最直接控制。
在 HarmonyOS NEXT 之前,开发者若要实现开关组件,通常使用 Switch(滑动开关)或 Checkbox(勾选框)等分散组件——它们的 API 不完全一致,类型之间无法统一管理。ArkUI 在 API 10 中推出了统一的 Toggle 组件,将三种开关形态(滑动开关、勾选框、按钮开关)整合到同一个组件接口下,通过 ToggleType 参数切换形态,使用统一的 isOn 和 onChange 管理状态。
本文通过一个应用功能开关面板 Demo 深入讲解 Toggle 组件的核心用法:三种类型的区别和适用场景、开关联动禁用、状态计数和恢复默认。阅读完本文,你将能够:
- 使用 Toggle 组件的三种类型(Switch / Checkbox / Button)
- 用
isOn和onChange管理开关状态 - 实现开关之间的联动逻辑(父子开关的自动禁用)
- 实现全局状态统计和一键恢复默认
二、Toggle 组件 API 总览
2.1 构造函数参数
Toggle({ type: ToggleType.Switch, isOn: true })
| 参数 | 类型 | 说明 |
|---|---|---|
type |
ToggleType |
开关类型:Switch(滑动开关)、Checkbox(勾选框)、Button(按钮开关) |
isOn |
boolean |
开关初始状态。true = 开启,false = 关闭 |
Toggle 是受控组件——它不维护内部状态,始终反映外部传入的 isOn 值。当用户点击 Toggle 时,视觉状态改变,但 isOn 值不会自动更新;开发者需要在 onChange 中手动更新 isOn 以保持 UI 一致性。
2.2 三种类型对比
ToggleType.Switch — 滑动开关
Toggle({ type: ToggleType.Switch, isOn: true })
.selectedColor('#1677FF')
滑动开关是一个椭圆形滑块——左=关(灰色),右=开(蓝色)。这是最常见的开关形态,iOS 和 Android 都使用这种样式作为设置的默认开关。
Switch 的优势是视觉最直观——一眼就能看出当前状态(开=有色,关=灰色)。适合需要快速扫视的开关密集场景(如设置列表)。
ToggleType.Checkbox — 勾选框
Toggle({ type: ToggleType.Checkbox, isOn: false })
.selectedColor('#1677FF')
勾选框是一个正方形框,选中时内部打勾。Checkbox 的视觉不如 Switch 直观(需要看清框内是否有勾),但它的文化认知度更高——在表单、协议同意、多选列表中,Checkbox 是用户最熟悉的交互模式。
Checkbox 适合"确认型"场景——如"我已阅读并同意协议"、“启用声音提醒”。这些场景中,用户不是在"快速切换",而是在"确认一个选择"。
ToggleType.Button — 按钮开关
Toggle({ type: ToggleType.Button, isOn: false })
.selectedColor('#1677FF')
按钮开关是一个圆角矩形按钮,按下态和弹起态有明显区别。Button 类型是三兄弟中最"重"的交互——它有一个实体按钮的外形和按下反馈,适合需要强调的开关(如"振动反馈"——用户需要明确感知这个功能的开启/关闭)。
| 类型 | 视觉形态 | 适用场景 | 交互感觉 |
|---|---|---|---|
| Switch | 椭圆滑块 | 设置列表(快速开关) | 轻量、直观 |
| Checkbox | 正方形勾选框 | 确认操作(协议、选项) | 传统、可靠 |
| Button | 圆角按钮 | 需要强调的功能开关 | 实体、确定 |
在同一个设置页面中混合使用不同类型是合理的——根据开关的"重要性"选择最合适的形态。例如"消息推送"用 Switch(高频率主开关),"声音提醒"用 Checkbox(子选项确认),"振动反馈"用 Button(需要明确感知)。
2.3 属性方法
selectedColor(value: ResourceColor)
设置开启状态的颜色:
Toggle({ type: ToggleType.Switch, isOn: true })
.selectedColor('#1677FF') // 蓝色开启态
selectedColor 是 Toggle 最常用的属性——它决定了开关的"主题色"。在 iOS 中默认为绿色(#34C759),在 Android 中默认为蓝色(#1976D2),在 HarmonyOS 中默认为系统主题色。推荐使用应用的品牌色或语义色。
enabled(value: boolean)
设置开关是否可交互:
Toggle({ type: ToggleType.Switch, isOn: false })
.enabled(false) // 禁用,灰色且不可点击
禁用的 Toggle 显示为灰色,用户点击无效。这是实现联动逻辑的关键属性——当父开关关闭时,子开关自动禁用。
2.4 事件回调
onChange(callback: (isOn: boolean) => void)
开关状态改变时触发:
Toggle({ type: ToggleType.Switch, isOn: this.pushEnabled })
.onChange((isOn: boolean) => {
this.pushEnabled = isOn;
if (!isOn) {
// 联动:关闭推送时,声音和振动也关闭
this.soundEnabled = false;
this.vibrateEnabled = false;
}
})
onChange 是 Toggle 的核心事件——用户点击开关后,回调接收新的 isOn 值。开发者需要在回调中做两件事:
- 更新对应状态变量(保证 Toggle 视觉与数据一致)
- 执行副作用(联动其他开关、保存设置、发送埋点等)

三、Demo 设计:应用功能开关面板
3.1 功能概述
Demo 模拟一个应用功能开关面板,包含 8 个设置项,分为 3 组:
消息通知组(3 项)
| 开关 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| 消息推送 | Switch | 开启 | 主开关,关闭时联动禁用子项 |
| 声音提醒 | Checkbox | 开启 | 子开关,推送关闭时自动禁用 |
| 振动反馈 | Button | 关闭 | 子开关,推送关闭时自动禁用 |
隐私设置组(3 项)
| 开关 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| 位置共享 | Switch | 关闭 | 敏感权限,默认关闭 |
| 个性化推荐 | Switch | 开启 | 可选功能 |
| 数据统计 | Switch | 开启 | 默认开启帮助改进产品 |
显示偏好组(2 项)
| 开关 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| 深色模式 | Switch | 关闭 | 视觉偏好 |
| 列表紧凑模式 | Switch | 关闭 | 信息密度偏好 |
顶部状态栏实时显示"已开启 X/8 项",底部"恢复默认"按钮一键重置所有开关到默认值。
3.2 数据结构
interface SettingItem {
key: string; // 唯一标识
label: string; // 显示名称
desc: string; // 描述文字
isOn: boolean; // 当前状态
defaultOn: boolean;// 默认状态(恢复默认时使用)
group: string; // 分组
type: ToggleType; // 开关类型
disabled: boolean; // 是否禁用
}
@State settings: SettingItem[] = [];
@State enabledCount: number = 0;
defaultOn 字段保存了每个开关的默认值——“恢复默认"功能依赖它。如果只保存 isOn 而不保存 defaultOn,就无法区分"用户手动关闭的"和"默认就是关闭的”。
disabled 字段由联动逻辑控制——当父开关(消息推送)关闭时,子开关(声音提醒、振动反馈)的 disabled 变为 true。
3.3 三种 Toggle 类型的实际使用
在 Demo 中,三种类型各有一个实例,各自服务于不同的交互场景:
Switch 类型(消息推送)
Toggle({ type: ToggleType.Switch, isOn: item.isOn })
.selectedColor('#1677FF')
.enabled(!item.disabled)
.onChange((isOn: boolean) => {
this.onToggleChange(item.key, isOn);
})
Switch 是最高频使用的开关类型——8 个设置中 6 个使用 Switch。它们的特点是:视觉直观、操作快、适合列表扫描。
Checkbox 类型(声音提醒)
Toggle({ type: ToggleType.Checkbox, isOn: item.isOn })
.selectedColor('#1677FF')
.enabled(!item.disabled)
.onChange((isOn: boolean) => {
this.onToggleChange(item.key, isOn);
})
Checkbox 用于"声音提醒"——它是"消息推送"的子选项,使用 Checkbox 而非 Switch 有三个原因:
- 视觉区分:在同一组中,主开关用 Switch,子开关用 Checkbox,用户自然建立层级感
- 确认语义:声音提醒不是高频切换项(用户不会频繁开关声音),Checkbox 的"确认"语义比 Switch 的"快速切换"更适合
- 文化习惯:声音相关设置在许多应用中都用 Checkbox(如 Android 的"铃声"设置)
Button 类型(振动反馈)
Toggle({ type: ToggleType.Button, isOn: item.isOn })
.selectedColor('#1677FF')
.width(48)
.enabled(!item.disabled)
.onChange((isOn: boolean) => {
this.onToggleChange(item.key, isOn);
})
Button 用于"振动反馈"——振动是一种触觉体验,Button 类型的按压反馈与振动的"触觉"语义一致。此外,振动的默认值是关闭的——这意味着大多数用户不会开启它,而 Button 类型的"实体感"让用户更慎重地考虑是否开启。
3.4 联动逻辑
消息通知组是 Demo 的核心交互——关闭"消息推送"时,声音和振动自动禁用:
onToggleChange(key: string, isOn: boolean): void {
const newSettings: SettingItem[] = [];
for (let i = 0; i < this.settings.length; i++) {
const s = this.settings[i];
if (s.key === key) {
// 更新触发的开关
newSettings.push({ ...s, isOn: isOn });
} else if (s.key === 'sound' || s.key === 'vibrate') {
if (key === 'push' && !isOn) {
// 推送关闭 → 子开关关闭且禁用
newSettings.push({ ...s, isOn: false, disabled: true });
} else if (key === 'push' && isOn) {
// 推送打开 → 子开关恢复默认且启用
newSettings.push({ ...s, isOn: s.defaultOn, disabled: false });
} else {
newSettings.push(s);
}
} else {
newSettings.push(s);
}
}
this.settings = newSettings;
this.countEnabled();
}
关键逻辑:
- 推送关闭时:声音和振动强制设为
false,disabled设为true - 推送重新开启时:声音和振动恢复到各自的默认值(声音=true,振动=false),
disabled恢复false - 其他开关的变化不影响子开关
这种"推送关闭 → 子开关禁用"的联动逻辑在很多真实应用中出现——iOS 的"通知"设置中,关闭"允许通知"会自动隐藏所有子选项。这里没有隐藏子开关而是显示为禁用态,因为禁用态能告知用户"这里还有选项,只是当前不可用"——比直接隐藏更有引导性。
3.5 状态计数
页面顶部的状态栏实时显示开启数量:
countEnabled(): void {
let n = 0;
for (let i = 0; i < this.settings.length; i++) {
if (this.settings[i].isOn) { n++; }
}
this.enabledCount = n;
}
每次 onToggleChange 或 resetAll 执行后调用 countEnabled 更新计数。这个数字提供了"全局视野"——用户无需逐一数开关,就能知道有多少功能处于开启状态。
3.6 恢复默认
resetAll(): void {
const newSettings: SettingItem[] = [];
for (let i = 0; i < this.settings.length; i++) {
const s = this.settings[i];
newSettings.push({
...s, isOn: s.defaultOn, disabled: false
});
}
this.settings = newSettings;
this.countEnabled();
// Toast 提示
this.showResetToast = true;
this.toastTimer = setInterval(() => {
clearInterval(this.toastTimer);
this.toastTimer = -1;
this.showResetToast = false;
}, 2000);
}
恢复默认将所有 isOn 重置为 defaultOn,所有 disabled 恢复 false。然后用一个 2 秒的 Toast(底部黑色文字条)给予视觉确认——“✓ 已恢复默认设置”。Toast 使用 setInterval 自清理模式,2 秒后自动消失。
3.7 页面结构
┌──────────────────────────────────────────┐
│ ⚙ 功能开关(深色标题栏) │
├──────────────────────────────────────────┤
│ 📘 Toggle 组件说明卡片 │
├──────────────────────────────────────────┤
│ ┌────────────────────────────────────┐ │
│ │ 已开启 5/8 项 恢复默认 │ │ ← 状态计数 + 恢复按钮
│ └────────────────────────────────────┘ │
├──────────────────────────────────────────┤
│ 消息通知 │ ← 分组标题
│ ┌────────────────────────────────────┐ │
│ │ 消息推送 [====] │ │ ← Switch(主开关)
│ │ 接收新消息和系统通知 │ │
│ │────────────────────────────────────│ │
│ │ 声音提醒 [✓] │ │ ← Checkbox(子开关)
│ │ 收到消息时播放提示音 │ │
│ │────────────────────────────────────│ │
│ │ 振动反馈 [按钮] │ │ ← Button(子开关)
│ │ 收到消息时振动设备 │ │
│ └────────────────────────────────────┘ │
├──────────────────────────────────────────┤
│ 隐私设置 │
│ ┌────────────────────────────────────┐ │
│ │ 位置共享 [ ] │ │
│ │ 个性化推荐 [====] │ │
│ │ 数据统计 [====] │ │
│ └────────────────────────────────────┘ │
├──────────────────────────────────────────┤
│ 显示偏好 │
│ ┌────────────────────────────────────┐ │
│ │ 深色模式 [ ] │ │
│ │ 列表紧凑模式 [ ] │ │
│ └────────────────────────────────────┘ │
├──────────────────────────────────────────┤
│ [✓ 已恢复默认设置](Toast) │
└──────────────────────────────────────────┘

四、Toggle 组件的最佳实践
4.1 三种类型的选择指南
| 场景 | 推荐类型 | 理由 |
|---|---|---|
| 主功能开关(高频率) | Switch | 视觉最直观,操作最快 |
| 子选项确认 | Checkbox | 文化和交互的"确认"语义 |
| 需要强调的功能 | Button | 实体按钮反馈,操作慎重 |
| 隐私/安全相关 | Switch + 二次确认 | Switch 快速看到状态,确认弹窗防止误操作 |
| 列表多选 | Checkbox | 多选是 Checkbox 的核心场景 |
| 协议同意 | Checkbox | "我已阅读"是确认行为,不是开关行为 |
4.2 联动设计
当多个开关存在关联关系时,有几种联动策略:
策略 1:自动禁用子开关(本 Demo 采用)
父开关关闭 → 子开关变灰且不可操作,但保留位置。适用场景:用户需要知道"还有这些子选项",但当前不可用。
策略 2:自动隐藏子开关
父开关关闭 → 子开关直接消失。适用场景:主开关关闭时子开关完全无意义(如"关闭 Wi-Fi"隐藏所有 Wi-Fi 网络列表)。
策略 3:子开关独立存在
父开关不联动子开关。适用场景:子开关即使脱离父开关也有独立的意义。
选择哪种策略取决于"用户是否需要看到被禁用的选项"。一般来说,如果子选项有独立的说明文字(如"收到消息时播放提示音"),禁用态比隐藏态更能教育用户。
4.3 默认值设计
默认值的选择应遵循"最小权限"原则:
- 敏感功能默认关闭:位置共享、麦克风权限、通知推送等——用户应主动选择开启
- 改善体验的功能默认开启:数据统计(匿名)、缓存优化——用户不需要感知
- 视觉偏好默认关闭:深色模式、紧凑布局——除非系统级深色模式已开启
本 Demo 中,隐私三项有两项默认开启(个性化推荐、数据统计),它们不是"权限型"开关,而是"偏好型"开关——默认开启不会对用户造成困扰。
4.4 开关文案
Toggle 组件的文字标签应遵循:
- 简短:控制在 4-6 个字(“消息推送”、“位置共享”、“深色模式”)
- 正面表述:使用"开启 XXX"而非"关闭 XXX"——开关的开启态代表正面行为
- 配描述:每个标签下方配一行小字的描述(12sp),帮助用户理解开关的具体效果
五、完整代码结构
TogglePage (~200 行)
├── 数据定义
│ └── SettingItem 接口 — key/label/desc/isOn/defaultOn/group/type/disabled
├── 状态变量
│ ├── @State settings[8] — 8 个设置项
│ ├── @State enabledCount — 开启计数
│ └── @State showResetToast — 恢复确认提示
├── 生命周期
│ ├── aboutToAppear() — 初始化 8 个设置项
│ └── aboutToDisappear() — 清理 Toast 定时器
├── 业务逻辑
│ ├── onToggleChange() — 更新开关 + 联动逻辑
│ ├── countEnabled() — 统计开启数量
│ └── resetAll() — 恢复默认 + Toast 提示
├── 视图
│ ├── 标题栏 — ⚙ 功能开关
│ ├── 说明卡片 — Toggle 组件介绍
│ ├── 状态栏 — 计数 + 恢复按钮
│ ├── 消息通知组(Switch/Checkbox/Button 各一)
│ ├── 隐私设置组(3 个 Switch)
│ ├── 显示偏好组(2 个 Switch)
│ └── Toast 浮层(条件渲染 + position)
└── @Builder
├── settingGroup() — 分组容器
└── settingRow() — 单行开关(Toggle + 标签 + 描述 + 分割线)
六、总结
本文通过一个应用功能开关面板 Demo 深入讲解了 HarmonyOS NEXT 中的 Toggle 开关组件。Toggle 将 Switch、Checkbox、Button 三种开关形态统一到同一组件接口下,通过 type 切换形态,通过 isOn 控制状态,通过 onChange 监听变化。
核心要点回顾:
-
三种类型各有语义:Switch 适合高频快速开关(设置列表),Checkbox 适合确认型操作(子选项、协议),Button 适合需要强调的功能(需要慎重开启/关闭)。不同类型的本质是交互心理的差异。
-
Toggle 是受控组件:它不维护内部状态——始终反映外部传入的
isOn值。开发者必须在onChange中更新状态变量,否则 Toggle 的视觉与数据会不一致。 -
联动逻辑通过不可变更新实现:关闭父开关时,遍历数组,修改子开关的
isOn和disabled字段,生成新数组赋值给@State。这种模式保证了联动逻辑的清晰性和可追溯性。 -
状态计数提供全局视野:"已开启 X/8 项"让用户无需逐一数开关就能了解全局状态。每次状态变更后调用
countEnabled更新计数。 -
恢复默认需要保存初始值:每个设置项增加
defaultOn字段记录默认状态,resetAll将所有isOn重置为defaultOn。2 秒 Toast 给予操作确认。
Toggle 组件是 ArkUI 中"统一接口、多种形态"设计哲学的典型代表——一个组件名、一套属性方法、一个事件回调,覆盖三种交互形态。这种设计让开发者不需要为 Switch 和 Checkbox 记忆两套不同的 API,也让页面上不同形态的开关可以共享相同的状态管理逻辑。
七、扩展思考
Toggle 组件解决了开关的 UI 和交互问题,但在真实设置页面中还有更多设计维度:
开关状态持久化:当前 Demo 的状态仅存在于页面生命周期——页面退出后状态丢失。在实际应用中,需要通过 @ohos.data.preferences 将开关状态持久化到本地存储,下次进入时恢复。
开关分组折叠:当设置项超过 10 个时,通常需要将分组折叠/展开,只显示当前活跃的分组。这与 Toggle 组件本身无关,是列表布局层的优化。
开关与用户权限的联动:HarmonyOS 的敏感权限(如位置、相机)有系统级授权弹窗。当用户开启"位置共享"时,应触发系统权限请求——Toggle 的 onChange 是触发权限请求的理想时机。
批量操作:除了"恢复默认",还可以提供"全部开启"、"全部关闭"等批量操作。这在多选项设置中比逐一操作更高效。
这些扩展说明:Toggle 是开关交互的最小单元,而一个完整的设置页面还需要状态持久化、权限集成、批量操作等上层逻辑。理解 Toggle 的核心机制(类型选择、受控模式、联动逻辑)是构建任何设置页面的基础。
更多推荐




所有评论(0)