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)
}
}