鸿蒙应用开发UI基础第十八节:表单交互核心组件Button、Radio、Toggle示例演示

【学习目标】

  1. 精准区分Button、Radio、Toggle组件的核心定位与适用场景,掌握选型逻辑;
  2. 掌握各组件的基础创建、样式定制、状态控制,适配不同交互场景;
  3. 熟练绑定核心事件,实现"选择-确认"类业务逻辑;
  4. 掌握组件组合使用技巧,完成表单提交、功能开关等高频场景开发。

一、组件核心认知

1.1 定位与差异

三类组件同属表单交互核心组件,但能力边界和业务适配性明确区分,禁止跨场景混用:

组件 核心定位 核心特性 典型业务场景
Button 操作触发/指令提交 支持文本/复合样式、4种内置类型、点击反馈 表单提交、页面跳转、功能触发(确认/取消)
Radio 单选项互斥选择 同一group仅选一个、支持自定义选中样式 性别选择、支付方式、模式切换(响铃/振动)
Toggle 二元状态切换(开关/勾选) 3种样式(Switch/Checkbox/Button)、状态持久化 WiFi/蓝牙开关、协议勾选、夜间模式切换

二、工程基础配置

基于**HarmonyOS NEXT/API 20+**创建FormInteractionDemo工程,标准目录结构如下:

复制代码
FormInteractionDemo/
├── AppScope/
│   └── app.json5  // 全局配置
├── entry/
│   ├── src/main/
│   │   ├── ets/
│   │   │   ├── entryability/
│   │   │   │   └── EntryAbility.ets  // 应用入口
│   │   │   ├── pages/
│   │   │   │   ├── Index.ets  // 导航主页面
│   │   │   │   ├── ButtonDemoPage.ets  // Button组件实战
│   │   │   │   ├── RadioDemoPage.ets   // Radio组件实战
│   │   │   │   └── ToggleDemoPage.ets  // Toggle组件实战
│   │   ├── resources/
│   │   │   └── media/  // 图标素材
│   │   └── module.json5  // 模块配置

2.1 导航主页面(Index.ets)

javascript 复制代码
import { router } from '@kit.ArkUI';

interface RouterItem {
  title: string;
  url: string;
}

@Entry
@Component
struct Index {
  private routerList: RouterItem[] = [
    { title: "Button按钮组件", url: 'pages/ButtonDemoPage' },
    { title: "Radio单选框组件", url: 'pages/RadioDemoPage' },
    { title: "Toggle切换组件", url: 'pages/ToggleDemoPage' }
  ];

  build() {
    Column({ space: 15 }) {
      Text("表单交互组件实战")
        .fontSize(30)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 40 })
        .textAlign(TextAlign.Center);

      ForEach(
        this.routerList,
        (item: RouterItem) => {
          Button(item.title)
            .width('80%')
            .height(45)
            .backgroundColor($r('sys.color.brand'))
            .fontColor(Color.White)
            .fontSize(16)
            .borderRadius(8)
            .shadow({ radius: 3, color: '#00000015', offsetX: 0, offsetY: 2 })
            .onClick(() => {
              router.pushUrl({ url: item.url });
            });
        },
        (item:RouterItem) => item.url
      );
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .backgroundColor('#F8F8F8')
    .padding(20);
  }
}

运行效果

三、Button按钮组件

3.1 核心知识点

  1. 四种内置类型
    • Capsule(胶囊型):默认类型,圆角为高度的1/2,不支持自定义圆角;
    • Circle(圆形):需设置宽高一致,适配悬浮操作按钮;
    • Normal(普通型):默认无圆角,支持borderRadius自定义;
    • ROUNDED_RECTANGLE(圆角矩形):默认圆角适配控件尺寸。
  2. 核心能力
    • 复合内容:支持嵌套单个子组件(如Row+Image+Text实现图文按钮);
    • 状态控制:enabled(布尔值)控制禁用状态(true=启用,false=禁用)、stateEffect关闭点击反馈;
    • 事件绑定:核心onClick事件,响应业务逻辑。

3.2 示例代码

javascript 复制代码
import { promptAction } from '@kit.ArkUI';

@Entry
@Component
struct ButtonDemoPage {
  @State isDisabled: boolean = false; // true=禁用,false=启用

  build() {
    Scroll() {
      Column({ space: 20 }) {
        Text("Button核心类型演示")
          .fontSize(22)
          .fontWeight(FontWeight.Medium)
          .alignSelf(ItemAlign.Start);

        // 1. 胶囊按钮(默认类型)
        Button("胶囊按钮(默认)", { type: ButtonType.Capsule })
          .width('80%')
          .height(45)
          .backgroundColor($r('sys.color.brand'))
          .fontColor(Color.White)
          .onClick(() => {
            promptAction.showToast({ message: '胶囊按钮点击' });
          });

        // 2. 圆形按钮(需宽高一致)
        Button({ type: ButtonType.Circle, stateEffect: true }) {
          Image($r('app.media.icon_add')) // 需放入media目录
            .width(24)
            .height(24);
        }
        .width(60)
        .height(60)
        .backgroundColor($r('sys.color.brand'));

        // 3. 普通按钮(自定义圆角)
        Button("普通按钮(自定义圆角)", { type: ButtonType.Normal })
          .width('80%')
          .height(45)
          .borderRadius(4)
          .backgroundColor('#667788')
          .fontColor(Color.White);

        // 4. 圆角矩形按钮
        Button("圆角矩形按钮", { type: ButtonType.ROUNDED_RECTANGLE })
          .width('80%')
          .height(45)
          .backgroundColor($r('sys.color.brand'))
          .fontColor(Color.White);

        Divider().width('100%');

        Text("Button状态与交互")
          .fontSize(22)
          .fontWeight(FontWeight.Medium)
          .alignSelf(ItemAlign.Start);

        // 禁用状态切换按钮
        Button(this.isDisabled ? "启用按钮" : "禁用按钮")
          .width('80%')
          .height(45)
          .backgroundColor(this.isDisabled ? '#CCCCCC' : $r('sys.color.brand'))
          .fontColor(Color.White)
          .onClick(() => {
            this.isDisabled = !this.isDisabled;
          });

        // 可交互/禁用按钮(核心:使用enabled属性)
        Button("可点击按钮(带禁用)")
          .width('80%')
          .height(45)
          .enabled(!this.isDisabled) // enabled=false时禁用
          .backgroundColor($r('sys.color.brand'))
          .fontColor(Color.White)
          .onClick(() => {
            promptAction.showToast({ message: '可点击按钮触发' });
          });

        // 5. 复合按钮(文字+图标)
        Button({ type: ButtonType.Capsule }) {
          Row({ space: 8}) {
            Image($r('app.media.icon_search'))
              .width(20)
              .height(20);
            Text("搜索")
              .fontSize(16)
              .fontColor(Color.White);
          }.alignItems(VerticalAlign.Center)
        }
        .width('80%')
        .height(45)
        .backgroundColor('#6A5ACD');

        // 6. 无点击反馈按钮
        Button("无点击反馈按钮", { stateEffect: false })
          .width('80%')
          .height(45)
          .backgroundColor('#999999')
          .fontColor(Color.White);
      }
      .width('100%')
      .padding(20)
      .backgroundColor('#F8F8F8');
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F8F8F8');
  }
}

四、Radio单选框组件

4.1 核心知识点

  1. 核心属性
    • value:Radio的唯一标识,字符串类型;
    • group:分组名称,同一group的Radio互斥,字符串类型;
    • checked:是否选中,布尔类型(默认false);
    • enabled:是否启用,布尔类型(默认true);
    • indicatorType:选中指示器类型(如DOT/TICK/CUSTOM),枚举类型;
    • indicatorBuilder:自定义指示器构建函数(仅indicatorType=CUSTOM时生效);
    • radioStyle:Radio样式配置,包含checkedBackgroundColor(选中背景色)、indicatorColor(指示器颜色)等;
  2. 核心事件
    • onChange:选中状态变化时触发,返回参数为isChecked: boolean

4.2 示例代码

javascript 复制代码
import { promptAction } from '@kit.ArkUI';

@Entry
@Component
struct RadioDemoPage {
  // 绑定选中状态,默认值匹配Radio的value
  @State selectedSoundMode: string = 'ring';
  @State dataSource: Record<string, string> = {
    'ring': '响铃模式',
    'vibrate': '振动模式',
    'silent': '静音模式'
  }
  // 同一分组名称
  private soundGroup: string = 'soundModeGroup';

  // 自定义指示器构建函数
  @Builder
  customIndicatorBuilder() {
    Image($r('app.media.star')) // 需在media目录放入star图标
      .width(16)
      .height(16)
      .fillColor(Color.Yellow);
  }

  build() {
    Column({ space: 20 }) {
      Text("Radio单选框(分组互斥+自定义样式)")
        .fontSize(22)
        .fontWeight(FontWeight.Medium);

      // Radio分组容器
      Column({ space: 15 }) {
        // 1. 响铃模式(DOT类型指示器)
        Radio({ value: 'ring', group: this.soundGroup,indicatorType:RadioIndicatorType.DOT })
          .checked(this.selectedSoundMode === 'ring')
          .radioStyle({ // Radio样式配置(官方属性)
            checkedBackgroundColor: Color.Pink, // 选中背景色
            indicatorColor: Color.Blue // 指示器颜色
          })
          .onChange((isChecked: boolean) => {
            if (isChecked) {
              this.selectedSoundMode = 'ring';
              promptAction.showToast({ message: '选择了响铃模式' });
            }
          });
        Text("响铃模式")
          .fontSize(16);

        // 2. 振动模式(CUSTOM自定义指示器)
        Radio({ value: 'vibrate',
          group: this.soundGroup,
          indicatorType:RadioIndicatorType.CUSTOM,
          // 绑定自定义构建函数
           indicatorBuilder:() => this.customIndicatorBuilder()})
          .checked(this.selectedSoundMode === 'vibrate')
          .radioStyle({
            checkedBackgroundColor: Color.Pink
          })
          .onChange((isChecked: boolean) => {
            if (isChecked) {
              this.selectedSoundMode = 'vibrate';
              promptAction.showToast({ message: '选择了振动模式' });
            }
          });
        Text("振动模式")
          .fontSize(16);

        // 3. 静音模式(TICK对勾指示器)
        Radio({ value: 'silent', group: this.soundGroup,indicatorType:RadioIndicatorType.TICK })
          .checked(this.selectedSoundMode === 'silent')
          .radioStyle({
            checkedBackgroundColor: Color.Pink
          })
          .onChange((isChecked: boolean) => {
            if (isChecked) {
              this.selectedSoundMode = 'silent';
              promptAction.showToast({ message: '选择了静音模式' });
            }
          });
        Text("静音模式")
          .fontSize(16);
      }
      .padding(20)
      .backgroundColor('#F5F5F5')
      .borderRadius(8)
      .width('90%');

      // 展示选中结果
      Text(`当前选中:${this.dataSource[this.selectedSoundMode]}`)
        .fontSize(14)
        .fontColor('#666');
    }
    .width('100%')
    .height('100%')
    .padding(20)
    .backgroundColor('#F8F8F8')
    .justifyContent(FlexAlign.Center);
  }
}

五、Toggle切换组件

5.1 核心知识点

  1. 三种核心类型
    • ToggleType.Switch:开关样式(适配WiFi/蓝牙开关);
    • ToggleType.Checkbox:勾选框样式;
    • ToggleType.Button:状态按钮样式(支持嵌套单个子组件)。
  2. 核心能力
    • isOn:设置初始状态(开启/选中为true);
    • selectedColor:设置选中/开启状态颜色(Toggle原生属性,非Radio);
    • switchPointColor:仅Switch类型生效,设置滑块颜色;
    • onChange:响应状态切换,返回当前状态值。

5.2 示例代码

javascript 复制代码
import { promptAction } from '@kit.ArkUI';

@Entry
@Component
struct ToggleDemoPage {
  // Switch状态
  @State isBluetoothOn: boolean = false;
  // Checkbox状态
  @State isAgreeProtocol: boolean = false;
  // Button类型状态
  @State isNightMode: boolean = false;

  build() {
    Column({ space: 25 }) {
      Text("Toggle核心类型演示")
        .fontSize(22)
        .fontWeight(FontWeight.Medium);

      // 1. Switch开关(WiFi/蓝牙场景)
      Row({ space: 0}) {
        Text("蓝牙开关")
          .fontSize(16);
        Toggle({ type: ToggleType.Switch, isOn: this.isBluetoothOn })
          .selectedColor($r('sys.color.brand')) // Toggle原生属性
          .switchPointColor(Color.White)
          .onChange((isOn: boolean) => {
            this.isBluetoothOn = isOn;
            promptAction.showToast({ message: `蓝牙${isOn ? '开启' : '关闭'}` });
          });
      }.alignItems(VerticalAlign.Center)
      .width('90%')
      .padding(10)
      .backgroundColor('#F5F5F5')
      .borderRadius(8);

      // 2. Checkbox勾选框(协议勾选)
      Row({ space: 10 }) {
        Toggle({ type: ToggleType.Checkbox, isOn: this.isAgreeProtocol })
          .selectedColor($r('sys.color.brand'))
          .onChange((isOn: boolean) => {
            this.isAgreeProtocol = isOn;
          });
        Text("我已阅读并同意用户协议和隐私政策")
          .fontSize(14)
          .fontColor('#666');
      }
      .alignItems(VerticalAlign.Center)
      .width('90%')
      .padding(10)
      .backgroundColor('#F5F5F5')
      .borderRadius(8);

      // 3. Button类型(状态切换按钮)
      Toggle({ type: ToggleType.Button, isOn: this.isNightMode }) {
        Text(this.isNightMode ? '夜间模式(开启)' : '夜间模式(关闭)')
          .fontSize(16)
          .fontColor(this.isNightMode ? Color.White : Color.Black);
      }
      .selectedColor($r('sys.color.brand'))
      .width('90%')
      .height(45)
      .onChange((isOn: boolean) => {
        this.isNightMode = isOn;
        promptAction.showToast({ message: `夜间模式${isOn ? '开启' : '关闭'}` });
      });
    }
    .width('100%')
    .height('100%')
    .padding(20)
    .backgroundColor('#F8F8F8')
    .justifyContent(FlexAlign.Center);
  }
}

六、核心知识点总结

6.1 组件选型关键

  1. 触发操作选Button:表单提交、页面跳转、功能触发等"一次性操作"场景;
  2. 单选互斥选Radio:多选项中仅选一个,支持自定义选中样式(indicatorType/indicatorBuilder);
  3. 二元切换选Toggle
    • 功能开关→Switch类型;
    • 协议勾选→Checkbox类型;
    • 状态按钮→Button类型。

6.2 开发避坑要点

  1. Button组件:
    • 禁用状态用enabled(true=启用,false=禁用);
  2. Radio组件:
    • 互斥依赖group属性,同组必须保证group值一致;
    • radioStyle可设置底框色
    • indicatorType:可设置样式和自定义样式(关于自定义组件我们后边会讲到);
  3. Toggle组件:
    • switchPointColor仅对Switch类型生效;
    • selectedColor是其原生属性,用于设置选中颜色;

七、配套代码

八、下节预告

下一节我们将学习ArkTS 状态管理 V1 基础篇,系统掌握鸿蒙声明式 UI 开发中"数据驱动视图"的核心机制:

  1. 理解状态管理核心概念与运行原理,掌握依赖收集、最小化更新的底层逻辑,区分状态变量与普通变量的本质差异;
  2. 精通 @State、@Prop、@Link、@Watch 四大基础装饰器的用法、核心差异与适用场景:
  3. 解决"状态更新但 UI 不刷新""@Link 传值编译报错""@Watch 不触发"等高频问题。

学完本节,你将建立"数据驱动视图"的核心思维,掌握鸿蒙声明式 UI 开发的底层核心能力,为后续复杂交互场景开发筑牢基础。

相关推荐
●VON2 小时前
2G 内存云服务器部署 Spring Boot + MySQL 实战:从踩坑到上线
服务器·开发语言·spring boot·mysql·ui·von
不要卷鸿蒙啊17 小时前
【鸿蒙开发】HMRouter一款和好用的管理路由三方工具
前端·harmonyos
chenyingjian18 小时前
鸿蒙|性能优化-渲染丢帧优化
harmonyos
ujainu20 小时前
在 HarmonyOS PC 上实现自定义窗口样式的 Electron 应用详解
华为·electron·harmonyos
ujainu21 小时前
Electron 极简时钟应用开发全解析:托盘驻留、精准北京时间与 HarmonyOS PC 适配实战
javascript·electron·harmonyos
Swift社区21 小时前
ArkUI 如何设计 AI 原生 UI?
人工智能·ui
盐焗西兰花21 小时前
鸿蒙学习实战之路-Share Kit系列(10/17)-目标应用接收分享(应用内处理)
学习·华为·harmonyos
大雷神1 天前
HarmonyOS APP<玩转React>开源教程八:主题系统实现
react.js·开源·harmonyos
fei_sun1 天前
【鸿蒙智能硬件】(六)使用鸿蒙app展示环境监测数据
华为·harmonyos