ArkUI Radio:单选有边界,用户才不迷路

举报
蓝瘦的蜕变 发表于 2026/08/25 18:48:56 2026/08/25
【摘要】 这篇我们单独看 Radio。 Radio 最适合互斥选择:一组选项里只能选一个。新手很容易把它和 Checkbox 混着用,结果页面看起来能多选,实际业务又只认一个值,用户就会迷糊。 所以这个 Demo 不写表单提交,也不讲状态刷新。我们先把 Radio 自己的边界看清楚:同组单选、默认选中、样式颜色和禁用态。 参考文

ArkUI Radio:单选有边界,用户才不迷路

这篇我们单独看 Radio

Radio 最适合互斥选择:一组选项里只能选一个。新手很容易把它和 Checkbox 混着用,结果页面看起来能多选,实际业务又只认一个值,用户就会迷糊。

所以这个 Demo 不写表单提交,也不讲状态刷新。我们先把 Radio 自己的边界看清楚:同组单选、默认选中、样式颜色和禁用态。

参考文档:

  • https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkui
  • https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-ui-development

同组单选才是 Radio 的重点

Radio 创建时要给 valuegroup

Radio({ value: 'daily', group: 'notifyFrequency' })
  .checked(true)

group 表示它属于哪一组。语义上,同一组里的选项互斥,只能选一个。

这里我们先用静态页面展示默认状态,不写 onChange。这不是偷懒,而是为了把组件本身讲清楚。状态变化后面会放到状态管理章节。

默认选中要有理由

默认项不是随便选一个。比如“轻量、标准、完整”三种模式里,案例默认选“标准模式”,因为它更像大多数用户的起点。

Radio({ value: 'standard', group: 'mode' })
  .checked(true)

如果默认项选得太激进,用户还没看懂页面,就已经被你带到一个特殊配置里了。

radioStyle 负责颜色细节

radioStyle 可以改选中背景、未选中边框和中间指示点颜色。

Radio({ value: 'daily', group: 'notifyFrequency' })
  .radioStyle({
    checkedBackgroundColor: '#2563EB',
    uncheckedBorderColor: '#CBD5E1',
    indicatorColor: '#FFFFFF'
  })

选中颜色可以跟当前模块主色走,未选中边框则建议轻一点。边框太重,页面会到处都是圆点,反而不好扫。

禁用态别只变灰

禁用态很简单:

Radio({ value: 'company', group: 'policy' })
  .checked(true)
  .enabled(false)

但只变灰不够。案例里把原因写在旁边:由管理员统一配置、试用结束后开放。用户知道为什么不能点,就不会怀疑页面出错。

打开案例页时,可以看三件事:同组是否互斥,默认项是否合理,禁用项是否说清原因。你现在项目里有没有那种“看着能多选,其实只能选一个”的设置?这种地方通常就该换成 Radio。

完整示例代码

文件位置:entry/src/main/ets/pages/arkUI/basic/ArkUIRadioDemo.ets

@Entry
@Component
struct ArkUIRadioDemo {
  @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
  radioRow(title: string, desc: string, group: string, value: string, checked: boolean, enabled: boolean,
    checkedColor: string, uncheckedColor: string, indicatorColor: string, borderColor: string) {
    Row({ space: 12 }) {
      Radio({ value: value, group: group })
        .checked(checked)
        .radioStyle({
          checkedBackgroundColor: checkedColor,
          uncheckedBorderColor: uncheckedColor,
          indicatorColor: indicatorColor
        })
        .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 Radio')
          .width('100%')
          .fontSize(24)
          .fontWeight(700)
          .fontColor('#0F172A')

        Text('单选有边界,用户才不迷路')
          .width('100%')
          .fontSize(22)
          .fontWeight(700)
          .fontColor('#111827')

        Text('这一页只看 Radio 自己:同组单选、默认选中、样式颜色和禁用态。复杂表单和状态刷新,先不放进来。')
          .width('100%')
          .fontSize(14)
          .fontColor('#64748B')
          .lineHeight(22)

        Column({ space: 12 }) {
          this.sectionTitle('同一组只能选一个', 'Radio 适合互斥选择。比如提醒频率,只能每天、每周、每月选一个。')

          this.radioRow('每天提醒', '适合高频任务,用户会更常收到提示。', 'notifyFrequency', 'daily', true, true,
            '#2563EB', '#CBD5E1', '#FFFFFF', '#BFDBFE')
          this.radioRow('每周提醒', '适合不紧急但要定期回看的内容。', 'notifyFrequency', 'weekly', false, true,
            '#2563EB', '#CBD5E1', '#FFFFFF', '#BFDBFE')
          this.radioRow('每月提醒', '适合低频复盘,不要打扰太多。', 'notifyFrequency', 'monthly', false, true,
            '#2563EB', '#CBD5E1', '#FFFFFF', '#BFDBFE')
        }
        .width('100%')
        .padding(16)
        .backgroundColor('#EFF6FF')
        .borderRadius(8)

        Column({ space: 12 }) {
          this.sectionTitle('默认选中要有理由', '默认项不是随便勾一个。案例里默认选“标准模式”,因为它最稳,也最少惊扰用户。')

          this.radioRow('轻量模式', '提示少一点,适合只想看重点的人。', 'mode', 'light', false, true,
            '#0F766E', '#99F6E4', '#FFFFFF', '#CCFBF1')
          this.radioRow('标准模式', '信息量适中,适合作为默认选择。', 'mode', 'standard', true, true,
            '#0F766E', '#99F6E4', '#FFFFFF', '#CCFBF1')
          this.radioRow('完整模式', '提示更多,适合需要盯细节的人。', 'mode', 'full', false, true,
            '#0F766E', '#99F6E4', '#FFFFFF', '#CCFBF1')
        }
        .width('100%')
        .padding(16)
        .backgroundColor('#F0FDFA')
        .borderRadius(8)

        Column({ space: 12 }) {
          this.sectionTitle('禁用态要说明不是没点准', '不能选的时候,旁边文案要解释原因,别只让圆点变灰。')

          this.radioRow('企业统一策略', '当前账号由管理员统一配置,个人暂时不能修改。', 'policy', 'company', true, false,
            '#64748B', '#CBD5E1', '#FFFFFF', '#CBD5E1')
          this.radioRow('试用结束后开放', '正式开通后才可以切到这个选项。', 'policy', 'trial', false, false,
            '#64748B', '#CBD5E1', '#FFFFFF', '#CBD5E1')
        }
        .width('100%')
        .padding(16)
        .backgroundColor('#F8FAFC')
        .borderRadius(8)
      }
      .width('100%')
      .padding(20)
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#FFFFFF')
  }
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。