鸿蒙开发笔记-21-ArkUI:按钮、单选框、切换按钮、进度条

内容分享2天前发布
1 0 0

ArkUI作为HarmonyOS的UI开发框架,提供了丰富的组件库帮助开发者快速构建应用界面。本文将介绍四个常用基础组件——按钮(Button)单选框(Radio)切换按钮(Toggle)进度条(Progress)

一、按钮组件 (Button)

按钮是交互界面的核心元素,ArkUI提供了灵活的按钮创建方式和样式定制能力。

属性 类型 作用

type
ButtonType 控制样式(Normal/Capsule/Circle)

stateEffect
boolean 启用点击反馈特效

borderRadius
number 圆角大小(仅Normal类型有效)

重要操作建议使用
stateEffect: true
禁用状态通过
disabled: true
实现

创建基础按钮

ArkUI提供三种内置按钮类型,每种类型有不同的默认样式和定制能力:

类型 特点 使用场景
Capsule 胶囊型(默认),圆角自动为高度一半 主要操作按钮
Circle 圆形按钮,宽高需一致 悬浮操作按钮(FAB)
Normal 矩形按钮,支持自定义圆角 次要操作或文本按钮

Button组件支持两种创建方式:文本按钮和包含子组件的复合按钮。


// 1. 文本按钮
Button('确认', { type: ButtonType.Normal, stateEffect: true })
  .borderRadius(8) //圆角大小(仅Normal类型有效)
  .backgroundColor(0x317aff)
  .width(90)
  .height(40)
//	stateEffect:启用点击反馈特效
        
// 2. 包含子组件的按钮
Button({ type: ButtonType.Capsule, stateEffect: true }) {
  Row() {
    Image($r('app.media.ic_arrow_right')).width(20).height(20)
    Text('下一步').fontSize(16).fontColor(Color.White)
  }.alignItems(VerticalAlign.Center)
}.width(150).height(45).backgroundColor(0x007DFF)

样式定制示例:


// API 11+ 新增按钮样式
Button('强调按钮')
  .buttonStyle(ButtonStyleMode.EMPHASIZED) // 强调样式
  .controlSize(ControlSize.LARGE) // 大型按钮
  .backgroundColor(0xFF007A)

Button('文字按钮')
  .buttonStyle(ButtonStyleMode.TEXT) // 文字样式(无背景)
  .fontColor(0x007DFF)
  
  

渐变背景按钮


Button('渐变')
.linearGradient({
  angle: 90,
  colors: [['#FF416C', 0.1], ['#FF4B2B', 0.9]]
})
.borderRadius(20)
.height(45)
事件处理

按钮最常用的事件是
onClick
点击事件:


Button('点击提示')
  .onClick(() => {
    promptAction.showToast({ message: '按钮被点击' })
  })
按钮状态管理

通过状态变量实现按钮的动态效果:


@State isFollowed: boolean = false

Button(this.isFollowed ? '已关注' : '关注')
  .backgroundColor(this.isFollowed ? 0xCCCCCC : 0x007DFF)
  .onClick(() => {
    this.isFollowed = !this.isFollowed
  })
  
// 使用状态变量控制按钮行为
@State isDisabled: boolean = false

Button('禁用状态')
.enabled(!this.isDisabled)
.backgroundColor(this.isDisabled ? '#CCCCCC' : '#2196F3')
.onClick(() => this.isDisabled = true)

二、单选框组件 (Radio)

单选框用于从一组选项中选择唯一选项,需通过
group
属性实现互斥选择。

基础用法

Column() {
  Radio({ value: 'opt1', group: 'theme' })
    .checked(true)
    .onChange((isChecked) => {
      if (isChecked) console.log('选择了浅色主题')
    })
  Text('浅色主题')
  
  Radio({ value: 'opt2', group: 'theme' })
    .onChange((isChecked) => {
      if (isChecked) console.log('选择了深色主题')
    })
  Text('深色主题')
}

注意:同一组单选框必须设置相同的
group
值才能实现互斥选择。

自定义样式

API 12+支持通过
contentModifier
自定义单选框样式:


class CustomRadioModifier implements ContentModifier<RadioConfiguration> {
  applyContent(): WrappedBuilder<[RadioConfiguration]> {
    return wrapBuilder((config: RadioConfiguration) => {
      Image(config.checked ? $r('app.media.radio_checked') : $r('app.media.radio_unchecked'))
        .width(24).height(24)
    })
  }
}

// 使用自定义样式
Radio({ value: 'custom', group: 'style' })
  .contentModifier(new CustomRadioModifier())
实战场景:设置页面选项

@State selectedSound: string = 'ring'

Column() {
  Text('通知铃声').fontSize(16).margin(10)
  
  Row({ space: 10 }) {
    Radio({ value: 'ring', group: 'sound' })
      .checked(this.selectedSound === 'ring')
      .onChange((isChecked) => {
        if (isChecked) this.selectedSound = 'ring'
      })
    Text('系统铃声')
    
    Radio({ value: 'vibrate', group: 'sound' })
      .checked(this.selectedSound === 'vibrate')
      .onChange((isChecked) => {
        if (isChecked) this.selectedSound = 'vibrate'
      })
    Text('振动模式')
  }
}

三、切换按钮 (Toggle)

三种切换样式
类型 适用场景 默认样式
Button 模式切换(如夜间模式) 文字标签
Checkbox 多选简化版 方形复选框
Switch 设备开关 圆形滑块

示例


Column({ space: 20 }) {
  // 1. 复选框(API 11+默认圆形)
  Toggle({ type: ToggleType.Checkbox, isOn: false })
    .selectedColor(Color.Pink)
  
  // 2. 开关
  Toggle({ type: ToggleType.Switch, isOn: true })
    .selectedColor(Color.Green)
    .switchPointColor(Color.White)
  
  // 3. 状态按钮
  Toggle({ type: ToggleType.Button, isOn: false }) {
    Text('夜间模式')
      .fontSize(14)
  }.width(120)
  .selectedColor(Color.Blue)
}
事件响应

通过
onChange
事件监听状态变化:


@State bluetoothOn: boolean = false

Toggle({ type: ToggleType.Switch, isOn: this.bluetoothOn })
  .onChange((isOn) => {
    this.bluetoothOn = isOn
    if (isOn) {
      promptAction.showToast({ message: '蓝牙已开启' })
    }
  })
样式定制

// 自定义开关颜色和大小
Toggle({ type: ToggleType.Switch, isOn: true })
  .selectedColor(Color.Orange)    // 开启状态颜色
  .switchPointColor(Color.Yellow) // 滑块颜色
  .width(60)                     // 开关宽度
  .height(30)                    // 开关高度

四、进度条组件 (Progress)

进度条用于展示操作进度,支持多种视觉样式和动态更新。

五种进度条类型
类型 特点 适用场景
Linear 直线进度 文件下载、内容加载
Ring 无刻度圆环 简单进度展示
ScaleRing 带刻度圆环 精准进度显示
Eclipse 实心圆形 完成率展示
Capsule 胶囊形状 数据上传/下载

Column({ space: 15 }) {
  // 1. 线性进度条
  Progress({ value: 30, total: 100, type: ProgressType.Linear })
    .width(200)
  
  // 2. 环形无刻度进度条
  Progress({ value: 40, total: 100, type: ProgressType.Ring })
    .width(80).height(80)
    .style({ strokeWidth: 8 })
  
  // 3. 环形有刻度进度条
  Progress({ value: 60, total: 100, type: ProgressType.ScaleRing })
    .width(80).height(80)
    .style({ scaleCount: 20, scaleWidth: 3 })
  
  // 4. 圆形进度条
  Progress({ value: 75, total: 100, type: ProgressType.Eclipse })
    .width(80).height(80)
  
  // 5. 胶囊进度条
  Progress({ value: 50, total: 100, type: ProgressType.Capsule })
    .width(150).height(30)
}
动态更新进度

通过状态变量绑定
value
属性实现动态更新:


@State progress: number = 0

Column() {
  Progress({ value: this.progress, total: 100, type: ProgressType.Capsule })
    .width(200).height(20)
  
  Button('增加进度')
    .onClick(() => {
      if (this.progress < 100) {
        this.progress += 10
      } else {
        this.progress = 0
      }
    })
}
实战场景:文件下载进度

@State downloadProgress: number = 0
private timer: number = -1

aboutToAppear() {
  // 模拟下载进度
  this.timer = setInterval(() => {
    if (this.downloadProgress < 100) {
      this.downloadProgress += 5
    } else {
      clearInterval(this.timer)
    }
  }, 500)
}

build() {
  Column() {
    Progress({ 
      value: this.downloadProgress, 
      total: 100, 
      type: ProgressType.Linear 
    })
    .width('90%')
    
    Text(`下载中: ${this.downloadProgress}%`)
      .fontSize(14)
      .margin(10)
  }
}

五、综合实战:设置页面

下面我们将四个组件组合使用,实现一个设置页面:


@Entry
@Component
struct SettingsPage {
  @State theme: string = 'light'
  @State notifications: boolean = true
  @State bluetooth: boolean = false
  @State volume: number = 60

  build() {
    Scroll() {
      Column({ space: 20 }) {
        // 主题设置(Radio)
        Column() {
          Text('主题设置').fontSize(18).margin(10)
          Row({ space: 20 }) {
            Radio({ value: 'light', group: 'theme' })
              .checked(this.theme === 'light')
              .onChange((isChecked) => {
                if (isChecked) this.theme = 'light'
              })
            Text('浅色')
            
            Radio({ value: 'dark', group: 'theme' })
              .checked(this.theme === 'dark')
              .onChange((isChecked) => {
                if (isChecked) this.theme = 'dark'
              })
            Text('深色')
          }
        }.width('100%').padding(15).backgroundColor(Color.White)

        // 通知设置(Toggle)
        Column() {
          Text('通知设置').fontSize(18).margin(10)
          Row() {
            Text('允许通知')
            Toggle({ type: ToggleType.Switch, isOn: this.notifications })
              .onChange((isOn) => this.notifications = isOn)
          }.justifyContent(FlexAlign.SpaceBetween)
        }.width('100%').padding(15).backgroundColor(Color.White)

        // 蓝牙设置(Toggle)
        Column() {
          Text('蓝牙').fontSize(18).margin(10)
          Row() {
            Text('开启蓝牙')
            Toggle({ type: ToggleType.Switch, isOn: this.bluetooth })
              .onChange((isOn) => this.bluetooth = isOn)
          }.justifyContent(FlexAlign.SpaceBetween)
        }.width('100%').padding(15).backgroundColor(Color.White)

        // 音量调节(Progress)
        Column() {
          Text('媒体音量').fontSize(18).margin(10)
          Progress({ value: this.volume, total: 100, type: ProgressType.Linear })
            .width('100%')
          Row({ space: 10 }) {
            Button('-')
              .width(40).height(40)
              .onClick(() => {
                if (this.volume > 0) this.volume -= 10
              })
            
            Button('+')
              .width(40).height(40)
              .onClick(() => {
                if (this.volume < 100) this.volume += 10
              })
          }.justifyContent(FlexAlign.Center)
        }.width('100%').padding(15).backgroundColor(Color.White)
      }.padding(10).backgroundColor(0xF5F5F5)
    }.backgroundColor(0xF5F5F5)
  }
}

我是今阳,如果想要进阶和了解更多的干货,欢迎关注微信公众号 “今阳说” 接收我的最新文章

© 版权声明

相关文章

暂无评论

none
暂无评论...