ArkUI Checkbox:多选不打架,选择才像选择
ArkUI Checkbox:多选不打架,选择才像选择
这篇我们单独看 Checkbox。
上一篇 Toggle 里已经见过 Checkbox 形态,但那只是为了分清几种开关外观。这一篇不绕了,我们就盯着真正的 Checkbox 组件:单个勾选、多个独立选择、颜色和禁用态。
先说清楚边界:这篇不讲成组管理,也不做全选、反选、列表刷新和表单提交。那些内容以后会放到对应章节。我们先把一个勾选框本身写稳。
参考文档:
- https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkui
- https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-ui-development
单个 Checkbox 先讲语义
Checkbox 适合“我选择了这个选项”。它不是持续生效的开关,所以像“我已阅读并同意服务说明”这种一次确认,用它比用 Switch 更自然。
Checkbox({ name: '我已阅读并同意服务说明' })
.select(true)
.selectedColor('#0F766E')
.unselectedColor('#94A3B8')
name 用来标识这个 Checkbox。select(true) 让它一开始就是选中状态。
这里最容易写错的不是代码,而是文案。旁边不要只写“同意”,最好写完整一点,让用户知道勾上以后到底代表什么。这个细节看起来小,但放到真实页面里,能少很多误点。
多个 Checkbox 可以彼此独立
如果几个选项之间没有互斥关系,就可以直接放多个 Checkbox。
Checkbox({ name: '消息通知' })
.select(true)
.selectedColor('#2563EB')
.unselectedColor('#CBD5E1')
Checkbox({ name: '活动提醒' })
.select(false)
.selectedColor('#2563EB')
.unselectedColor('#CBD5E1')
比如消息通知、活动提醒、安全告警,它们可以选一个,也可以选多个。这里不需要急着上成组选中逻辑。
成组管理不是不能用,只是它适合更复杂的场景。我们这一篇先讲独立选项,越少牵扯越容易看明白。
颜色别只盯选中态
selectedColor 很常用,能让勾选框跟页面主色走在一起。
Checkbox({ name: '加入本周清单' })
.select(true)
.selectedColor('#7C3AED')
.unselectedColor('#C4B5FD')
但 unselectedColor 也别忽略。未选中颜色太重,页面会显得每个框都在抢注意力;太浅,又可能让用户看不清边界。
案例里把选中态做得更明确,未选中态收得轻一点。不是说只能这么配色,重点是:选中和未选中都要被设计,不要只改一半。
禁用态要解释为什么不能改
enabled(false) 可以让 Checkbox 变成不可操作状态。
Checkbox({ name: '由组织统一开启' })
.select(true)
.selectedColor('#64748B')
.unselectedColor('#CBD5E1')
.enabled(false)
禁用态最怕只变灰,不解释。用户点不了,会先怀疑自己是不是没点准,或者页面是不是出了问题。
所以案例里把原因写在文案里:比如“当前账号属于企业空间,这项由管理员统一配置”。这句话不花哨,但很有用。
看案例时盯这几处
打开案例页后,我们不用急着改状态,先看几个视觉和语义点:
- 单个 Checkbox 是否表达了一次确认,而不是长期设置。
- 多个 Checkbox 是否是彼此独立的选择,没有强行绑成一组。
- 选中颜色和未选中颜色是否都被处理过。
- 禁用态是否不仅变灰,还解释了不能操作的原因。
这篇不跑 hvigor。你在 DevEco Studio 里打开案例页,看这些勾选项的摆放和文案就够了。
如果你现在手里有一个设置页,可以挑一组多选项看看:它们是真的可以多选,还是其实应该做成单选?这个判断很常见,也很容易一开始就写偏。
完整示例代码
文件位置:entry/src/main/ets/pages/arkUI/basic/ArkUICheckboxDemo.ets
@Entry
@Component
struct ArkUICheckboxDemo {
@Builder
sectionTitle(title: string, desc: string) {
Column({ space: 4 }) {
Text(title)
.width('100%')
.fontSize(16)
.fontWeight(700)
.fontColor('#0F172A')
Text(desc)
.width('100%')
.fontSize(13)
.fontColor('#64748B')
.lineHeight(20)
}
.width('100%')
.alignItems(HorizontalAlign.Start)
}
@Builder
optionText(title: string, desc: string, enabled: boolean) {
Column({ space: 4 }) {
Text(title)
.width('100%')
.fontSize(15)
.fontWeight(700)
.fontColor(enabled ? '#0F172A' : '#94A3B8')
Text(desc)
.width('100%')
.fontSize(12)
.fontColor(enabled ? '#64748B' : '#94A3B8')
.lineHeight(18)
}
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
}
@Builder
checkboxRow(title: string, desc: string, selected: boolean, enabled: boolean, selectedColor: string,
unselectedColor: string, borderColor: string) {
Row({ space: 12 }) {
Checkbox({ name: title })
.select(selected)
.selectedColor(selectedColor)
.unselectedColor(unselectedColor)
.enabled(enabled)
this.optionText(title, desc, enabled)
}
.width('100%')
.height(66)
.padding({ left: 14, right: 14, top: 12, bottom: 12 })
.backgroundColor(enabled ? '#FFFFFF' : '#F1F5F9')
.border({ width: 1, color: enabled ? borderColor : '#CBD5E1' })
.borderRadius(8)
}
build() {
Scroll() {
Column({ space: 18 }) {
Text('ArkUI Checkbox')
.width('100%')
.fontSize(24)
.fontWeight(700)
.fontColor('#0F172A')
Text('多选不打架,选择才像选择')
.width('100%')
.fontSize(22)
.fontWeight(700)
.fontColor('#111827')
Text('这一页只看 Checkbox 自己:单个勾选、多个独立选项、颜色和禁用态。复杂选择逻辑、全选反选和状态刷新,先不放进来。')
.width('100%')
.fontSize(14)
.fontColor('#64748B')
.lineHeight(22)
Column({ space: 12 }) {
this.sectionTitle('单个 Checkbox 先把语义说清楚', '它不是持续开关,而是“我选择了这个选项”。旁边文案最好直接说明选中以后代表什么。')
this.checkboxRow('我已阅读并同意服务说明', '适合一次确认,不适合做成 Switch。', true, true, '#0F766E',
'#94A3B8', '#BBF7D0')
}
.width('100%')
.padding(16)
.backgroundColor('#F0FDF4')
.borderRadius(8)
Column({ space: 12 }) {
this.sectionTitle('多个 Checkbox 可以彼此独立', '这几项没有互斥关系,用户可以选一个、选多个,也可以都不选。先别急着加成组管理。')
this.checkboxRow('消息通知', '收到评论、点赞和系统提醒时通知我。', true, true, '#2563EB',
'#CBD5E1', '#BFDBFE')
this.checkboxRow('活动提醒', '有活动开始前,再额外提醒一次。', false, true, '#2563EB',
'#CBD5E1', '#BFDBFE')
this.checkboxRow('安全告警', '登录异常、密码修改这类消息保持勾选。', true, true, '#2563EB',
'#CBD5E1', '#BFDBFE')
}
.width('100%')
.padding(16)
.backgroundColor('#EFF6FF')
.borderRadius(8)
Column({ space: 12 }) {
this.sectionTitle('颜色别只改选中态', '选中颜色能强调重点,未选中颜色也要收住,不然页面会显得每个框都在抢注意力。')
this.checkboxRow('加入本周清单', '选中态用紫色,适合和页面主色保持一致。', true, true, '#7C3AED',
'#C4B5FD', '#DDD6FE')
this.checkboxRow('稍后再看', '未选中态用浅灰紫,能看见边界,但不会太重。', false, true, '#7C3AED',
'#C4B5FD', '#DDD6FE')
}
.width('100%')
.padding(16)
.backgroundColor('#F5F3FF')
.borderRadius(8)
Column({ space: 12 }) {
this.sectionTitle('禁用态要顺手告诉用户原因', '不能改的时候,不要只把框变灰。旁边文案多写一句原因,用户就不会以为页面坏了。')
this.checkboxRow('由组织统一开启', '当前账号属于企业空间,这项由管理员统一配置。', true, false, '#64748B',
'#CBD5E1', '#CBD5E1')
this.checkboxRow('试用期结束后可选', '这个选项暂时不可用,正式开通后再开放。', false, false, '#64748B',
'#CBD5E1', '#CBD5E1')
}
.width('100%')
.padding(16)
.backgroundColor('#F8FAFC')
.borderRadius(8)
}
.width('100%')
.padding(20)
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
}
- 点赞
- 收藏
- 关注作者
评论(0)