鸿蒙应用开发-常用组件
第三节 常用组件
图片组件
名称:Image
作用:在页面中用于展示图片
参数:只有一个参数(三种类型string,Resource,media.PixelMap)
- string
- 本地路径:需要将自己新建的图片文件夹放在ets目录下面
- 网络路径:如果在真机上查看网络图片,需要配置网络访问权限,但是预览器和模拟器上不会限制
- Resource
- base
- element:存放一些预先配置好的json
- media:媒体资源(图片、音频、视频),需要使用r()方法引入,例如Image(r()方法引入,例如Image(r()方法引入,例如Image(r(‘app.media.img’))
- profile:自定义配置文件
- rawfile:存放任意格式的原始文件,需要使用rawfile()方法引入,例如Image(rawfile()方法引入,例如Image(rawfile()方法引入,例如Image(rawfile(‘icon.png’))
- base
- media.PixelMap:图片的像素位图,是一个二维数组,数组中的每个元素就是图片中的一个像素点,像素点包含了坐标和颜色值,通常用于图片的编辑
常用属性:
-
图片尺寸(width、height)
三种类型参数:
- string:包含了单位(百分号%——基于父元素而言;物理像素px——弊端:很难适应不同屏幕素质的设备;虚拟像素vp——相对单位,可以适应不同屏幕素质的设备)
- number:默认底层会分配vp作为单位
- Resource:在element目录里面配置宽度和高度值放在json文件里面,使用r()方法调用,例如r()方法调用,例如r()方法调用,例如r(‘app.json文件名.属性名’)
-
图片缩放:需要使用objectFit()方法设置,传入一个枚举对象(ImageFit)的选项值作为参数
- None:不做任何缩放,保持图片原尺寸显示
- Contain:按比例进行缩小或放大,使得图片能刚好装在组件中
- Cover:按照比例缩小或者放大,使得图片能完全装在组件中
- Fill:不会按照比例缩小或者放大,使得图片充满在组件中
- ScaleDown:按照比例缩小或不变(不会放大)
- Auto:自适应显示
-
图片插值:在一些出现模糊的图片补充一些像素,需要使用interpolation()方法设置,传入一个枚举对象(ImageInterpolation)的选项值作为参数
- None:不做插值(默认)
- Low:低等质量插值
- Medium:中等质量插值
- High:高等质量插值
注意事项:
- 资源管理:尤其注意图片的大小和分辨率
- 布局和显示:注意图片的尺寸和比例
- 交互设计:点击和手势操作、动画效果
- 兼容性和可访问性:注意在不同的屏幕上有一致的观感效果;网络图片的访问配置
文本组件
名称:Text
作用:在页面中用于显示文本内容
参数:只有一个参数(两种参数类型string、Resource)
- string:例如Text(‘我是一段文本’)
- Resource:需要预先在element目录配置好json文件,使用r()方法引入,例如Text(r()方法引入,例如Text(r()方法引入,例如Text(r(‘app.json文件名.字符串名称’))
常用属性:
-
字体大小:需要使用fontSize()方法设置
三种类型参数:
- string:需要带单位(物理像素px、字体像素fp(相对单位))
- number:底层会分配一个fp作为单位
- Resource:需要预先在element配置好json
-
字体粗细:需要使用fontWeight()方法设置
三种类型参数:
- string:注意只能写数值和枚举的选项,例如fontWeight(‘100’)或fontWeight(‘bold’)
- number:注意取值范围[100,900],默认是400
- fontWeight:Lighter——非常细、Normal——正常、Regular——常规、Medium——中等、Bold——较粗、Bolder——非常粗
-
字体颜色:需要使用fontColor()方法设置
四种类型参数:
- Color:例如Color.Green
- string:rgb()形式如’rgb(255,0,0)‘;rgba形式如’rgb(255,0,0,0.5)’;十六进制形式如’#ff0000’
- number:要用十六进制的数字,例如0x008000
- Resource:需要预先在element配置好json
-
文本对齐:需要使用textAlign()方法设置,传入一个枚举对象(TextAlign)的选项值作为参数
- Start:首部对齐
- Center:居中对齐
- End:末端对齐
-
最大行数设置和超长文本处理:需要使用maxLines()方法设置最大行数,textOverflow()方法处理超出部分
textOverflow()方法需传入一个对象形式的参数:
- {overflow:TextOverflow.Clip}(裁剪)
- {overflow:TextOverflow.Ellipsis}(省略号代替)
注意事项:
- 文本内容和格式:尤其要注意文本尽量不要超过Text组件的尺寸、
- 布局和尺寸:注意不同组件大小和屏幕尺寸
- 交互和响应
- 性能和资源管理
- 可访问性和国际化的问题
按钮组件
名称:Button
作用:用于响应页面中用户的点击操作
参数:两种使用方式
- 不包含子组件的时候:
- label:标签
- options(对象):type按钮类型——赋予一个枚举对象(ButtonType)的选项值(Capsule胶囊状、Circle圆形、Normal直角矩形);stateEffect是否开启点击效果(true/false)
- 包含子组件的时候:
- options(对象):type按钮类型——赋予一个枚举对象(ButtonType)的选项值(Capsule胶囊状、Circle圆形、Normal直角矩形);stateEffect是否开启点击效果(true/false)
常用属性:
-
背景色:需要使用backgroundColor()方法设置
四种类型参数:
- Color:例如Color.Green
- string:rgb()形式如’rgb(255,0,0)‘;rgba形式如’rgb(255,0,0,0.5)’;十六进制形式如’#ff0000’
- number:要用十六进制的数字,例如0x008000
- Resource:需要预先在element配置好json
-
边框圆角:需要使用borderRadius()方法设置,只有当按钮形状是直角矩形的时候才有意义
常用事件:点击事件,需要按钮绑定onClick()方法
注意事项:
- 功能设计:注意按钮的用途
- 外观设计:注意跟随系统的暗黑模式
- 交互设计:点击反馈
- 可访问性:注意特殊需求的用户
切换按钮组件
名称:Toggle
作用:在页面中切换不同状态
参数:只有一个参数(对象形式,包含两个属性)
- type:切换按钮形状,赋值为一个枚举对象(ToggleType)选项值(Switch(开关)、Checkbox(复选框)、Button(按钮,注意加个子组件))
- isOn:切换按钮的状态(true/false)
常用属性:
-
激活状态背景色:需要使用selectedColor()方法设置
参数:
- Color
- string:rgb()形式;rgba形式;十六进制形式
- number:十六进制的数字
- Resource
-
Switch滑块颜色:需要使用switchPointColor()方法设置
参数:
- Color
- string
- number
- Resource
常用事件:change状态改变事件,需要绑定onChange((isOn: boolen) => void)方法
注意事项:
- 功能明确性:在切换按钮之前加一些必要的标签
- 外观设计
- 交互反馈
- 可访问性:注意视力障碍的用户以及支持键盘的快捷操作
- 性能考虑:避免频繁更新以及内存管理,可以设置防抖和节流
文本输入组件
名称:TextInput
作用:用于接收用户输入的文本内容
参数:只有一个参数(对象形式,包含两个属性)
- placeholder:占位提示符(string、Resource)
- text:输入框当前的文本内容(string、Resource)
常用属性:
- 输入框类型:需要使用type()方法设置,传入一个枚举对象(InputType)的选项值作为参数
- Normal:基本输入模式,默认
- password:密码输入模式
- Number:数字输入模式
- 光标样式:需要使用caretColor()方法设置(Color、string、number、Resource)
- placeholder样式:使用placeholderFont()方法设置字体大小、字体粗细等;使用placeholderColor()设置字体颜色
- 文本样式:fontSize()、fontWeight()、fontColor()
常用事件:
- change事件:监听输入框内容的改变,需要绑定onChange((value: string) => void)方法
- 焦点事件:
- 获得焦点:需要绑定onFocus(() => void)方法
- 失去焦点:需要绑定onBlur(() => void)方法
注意事项:
- 用户体验方面:注意一些必要的提示,例如placeholder和标签,以及自动聚焦
- 功能实现方面:注意数据校验和安全性等
- 性能优化方面:尤其内存和缓存资源的运用
- 可访问性方面:注意视力障碍的用户的使用
进度条组件
名称:Progress
作用:显示各种进度
参数:只有一个参数(对象形式,包含三个属性)
- value:当前的进度值
- total:进度条的总值(不要超过100)
- type:进度条类型,赋予一个枚举对象(ProgressType)的选项值(Linear(线性)、Ring(环形)、ScaleRing(带有刻度的环形)、Eclipse(月食形状)、Capsule(胶囊状))
常用属性:
- 进度条样式:需要使用style()方法设置,传入一个对象形式的参数
- strokeWidth:进度条的宽度(粗细),注意只能作用于Linear/Ring/ScaleRing,默认是4vp
- scaleCount:进度条的刻度数,注意只能作用于ScaleRing,默认有120个刻度
- scaleWith:刻度线的宽度(粗细),默认是2vp
- 进度条颜色:通过backgroundColor()设置进度条的背景色,通过color()方法设置进度条的前景色
注意事项:
- 功能的准确性:注意进度条范围的设置以及当前进度的更新
- 用户体验:尤其注意给一些清晰的标识和反馈信息
- 性能优化:尤其要注意一些大量并发任务和长时间运行的任务
弹窗组件
作用:用于在页面中显示重要的信息,提示用户操作或收集用户信息
分类:
-
消息提示弹窗:
- 名称:Toast
- 作用:用于显示一些简短的消息或提示
- 用法:
- 导入promptAction模块
- 使用showToast方法显示,需要传入一个对象形式的参数
- message:提示的消息
- duration:停留时长,单位是ms,范围是[1500,10000]
- bottom:距离底部的距离
-
警告对话框:
-
名称:AlertDialog
-
作用:向用户发出警告或者二次确认操作的提示
-
用法:参考代码
Button('删除') .backgroundColor(Color.Red) .onClick(() => { AlertDialog.show({ // 标题 title: '温馨提示', // 内容 message: '删除之后无法恢复,您是否确认删除?', // 确认按钮 primaryButton: { // 标签 value: '删除', // 字体颜色 fontColor: '#ff0000', // 背景色 backgroundColor: '#fff', // 触发逻辑 action: () => {} }, // 取消按钮 secondaryButton: { // 标签 value: '取消', // 字体颜色 fontColor: '#0000ff', // 背景色 backgroundColor: '#fff', // 触发逻辑 action: () => {} }, // 位置 alignment: DialogAlignment.Bottom, // 偏移量 offset: { dx: 0, dy: -20 } }) })
-
-
操作列表弹窗:
-
名称:ActionSheet
-
作用:向用户提供一组选项,用户可以进行选择
-
用法:参考代码
Button('选择操作') .onClick(() => { ActionSheet.show({ // 标题 title: '文件操作', // 内容 message: '请选择倪要对文件执行的操作:', // 按钮 confirm: { // 标签 value: '取消', // 触发事件 action: () => { console.log('点击取消') } }, // 数组 sheets: [ { // 标题 title: '复制', // 图标 icon: $r('app.media.ic_copy'), // 触发事件 action: () => { console.log('文件复制操作') } }, { // 标题 title: '剪切', // 图标 icon: $r('app.media.ic_cut'), // 触发事件 action: () => { console.log('文件剪切操作') } }, { // 标题 title: '删除', // 图标 icon: $r('app.media.ic_delete'), // 触发事件 action: () => { console.log('文件删除操作') } }, ] }) })
-
-
选择器弹窗
-
作用:让用户从一个列表中选择一个具体的值
-
分类:
-
文本滑动选择器弹窗
-
名称:TextPickerDialog
-
用法:参考代码
@Entry @Component struct Index { @State message: string = '苹果' @State select: number = 0 private fruits: string[] = ['苹果', '西瓜', '雪梨', '橙子', '香蕉'] private fruits_color: string[] = ['#FFC0CB', '#90EE90', '#FFFF00', '#FFA07A', '#FFD700'] build() { // 外壳容器 Column({ space: 20 }) { Text(this.message) .fontSize(25) .fontWeight(FontWeight.Bold) .fontColor(this.fruits_color[this.select]) Button('选择水果') .onClick(() => { TextPickerDialog.show({ // 范围 range: this.fruits, // 下标 selected: this.select, // 确定方法 onAccept: (value: TextPickerResult) => { this.select = Number(value.index) this.message = this.fruits[this.select] console.log('最终选择的值为:', value.value) }, // 切换方法 onChange: (value: TextPickerResult) => { console.log('当前选择的值为:', value.value) }, // 取消方法 onCancel: () => { console.log('取消文本选择') } }) }) } .width('100%') // 宽度撑满整个屏幕 .height('100%') // 高度撑满整个屏幕 .justifyContent(FlexAlign.Center) // 居中 } }
-
-
日期滑动选择器弹窗
-
名称:DatePickerDialog
-
用法:参考代码
// 导入 dayjs库 import dayjs from 'dayjs' @Entry @Component struct Index { @State selectDate: string = dayjs(new Date('2025-1-1')).format('YYYY-MM-DD') build() { // 外壳容器 Column({ space: 20 }) { Text(this.selectDate) .fontSize(25) .fontWeight(FontWeight.Bold) Button('选择日期') .onClick(() => { DatePickerDialog.show({ // 开始日期 start: new Date('2010-1-1'), // 结束日期 end: new Date('2025-12-31'), // 选中的日期 selected: new Date(this.selectDate), // 确定方法 onAccept: (value: DatePickerResult) => { this.selectDate = dayjs(new Date(this.selectDate).setFullYear(value.year, value.month, value.day)).format('YYYY-MM-DD') console.log('最终选择的日期值为:', this.selectDate) }, // 切换的方法 onChange: (value: DatePickerResult) => { console.log('切换的日期值为:' + value.year + '-' + value.month + '-' + value.day) }, // 取消的方法 onCancel: () => { console.log('取消选择') } }) }) } .width('100%') // 宽度撑满整个屏幕 .height('100%') // 高度撑满整个屏幕 .justifyContent(FlexAlign.Center) // 居中 } }
-
-
时间滑动选择器弹窗
-
名称:TimePickerDialog
-
用法:参考代码
// 导入 dayjs库 import dayjs from 'dayjs' @Entry @Component struct Index { @State selectTime: string = dayjs(new Date('2025-7-15 10:30:00')).format('HH:mm') build() { // 外壳容器 Column({ space: 20 }) { Text(this.selectTime) .fontSize(25) .fontWeight(FontWeight.Bold) Button('选择时间') .onClick(() => { TimePickerDialog.show({ // 选择的时间 selected: new Date(this.selectTime), // 是否开启24小时制 useMilitaryTime: true, // 确定方法 onAccept: (time: TimePickerResult) => { this.selectTime = dayjs(new Date().setHours(time.hour, time.minute)).format('HH:mm') console.log('最终选择的时间值为:', this.selectTime) }, // 切换的方法 onChange: (time: TimePickerResult) => { console.log('切换的时间值为:' + time.hour + ':' + time.minute) }, // 取消的方法 onCancel: () => { console.log('取消选择') } }) }) } .width('100%') // 宽度撑满整个屏幕 .height('100%') // 高度撑满整个屏幕 .justifyContent(FlexAlign.Center) // 居中 } }
-
-
-
-
自定义弹窗
- 作用:适用于一些比较复杂的场景
- 用法:敬请期待
注意事项:
- 功能方面:尤其注意使用的目的以及生命周期管理
- 用户体验方面:注意外面和风格的统一性以及可操作性
- 可访问性方面:给一些特殊人群添加辅助功能
组件编程技巧
样式复用:
-
概念:当多个组件具有相同样式的时候,可以将些重复的代码单独抽离成一个方法,然后在需要的地方调用即可
-
方法:
-
@Styles方法:
-
组件内使用:请看具体案例
@Entry @Component struct Index { build() { // 外壳容器 Column({ space: 20 }) { Row({ space: 50 }) { Button('确认') .type(ButtonType.Normal) .compButtonStyle() // 调用复用样式 .backgroundColor(Color.Green) .onClick(() => { console.log('确认') }) Button('取消') .type(ButtonType.Normal) .compButtonStyle() // 调用复用样式 .backgroundColor(Color.Gray) .onClick(() => { console.log('取消') }) } } .width('100%') // 宽度撑满整个屏幕 .height('100%') // 高度撑满整个屏幕 .justifyContent(FlexAlign.Center) // 居中 } // 组件内样式复用 @Styles compButtonStyle() { .width(100) .height(40) .borderRadius(10) } } -
全局使用:请看具体案例
@Entry @Component struct Index { build() { // 外壳容器 Column({ space: 20 }) { Row({ space: 50 }) { Button('确认') .type(ButtonType.Normal) .backgroundColor(Color.Green) .globalButtonStyle() // 样式复用调用 .onClick(() => { console.log('确认') }) Button('取消') .type(ButtonType.Normal) .backgroundColor(Color.Gray) .globalButtonStyle() // 样式复用调用 .onClick(() => { console.log('取消') }) } } .width('100%') // 宽度撑满整个屏幕 .height('100%') // 高度撑满整个屏幕 .justifyContent(FlexAlign.Center) // 居中 } } // 全局样式复用 @Styles function globalButtonStyle() { .width(100) .height(40) .borderRadius(10) } -
注意:
- 组件内的@styles方法只能在当前组件内使用,全局的@Styles方法只能在当前的.ets文件中使用
- 组件内定义的@styles方法不需要使用function关键字,但是全局的要使用
- @styles方法中只能包含通用的属性和通用的事件方法
- @styles方法不支持参数
-
-
@Extend方法
-
只能全局使用,而且只能用于指定类型的组件:请看具体案例
@Entry @Component struct Index { build() { // 外壳容器 Column({ space: 20 }) { Row({ space: 50 }) { Button('确认') .buttonExtendStyle(Color.Green, () => console.log('确定')) // 样式复用调用 Button('取消') .buttonExtendStyle(Color.Gray, () => console.log('取消')) // 样式复用调用 } } .width('100%') // 宽度撑满整个屏幕 .height('100%') // 高度撑满整个屏幕 .justifyContent(FlexAlign.Center) // 居中 } } // 全局样式复用 @Extend(Button) function buttonExtendStyle(color: Color, callback: () => void) { .width(100) .height(40) .borderRadius(10) .type(ButtonType.Normal) .backgroundColor(color) .onClick(callback) } -
注意:
- 使用范围只能限于当前的.ets文件
- 可包含组件的专有属性和专有事件方法
- 支持参数
-
-
UI结构复用:
-
概念:当页面有多个相同的UI结构时,可以把相同的结构抽离封装成方法,然后在需要的地方调用即可
-
方法:@Builder方法
-
组件内使用:请看具体案例
@Entry @Component struct Index { build() { // 外壳容器 Column({ space: 20 }) { Row({ space: 50 }) { // UI结构调用 this.compButtonBuilder($r('app.media.ic_edit'), '编辑', () => console.log('编辑')) this.compButtonBuilder($r('app.media.ic_share'), '发送', () => console.log('发送')) } } .width('100%') // 宽度撑满整个屏幕 .height('100%') // 高度撑满整个屏幕 .justifyContent(FlexAlign.Center) // 居中 } // 组件内UI结构复用 @Builder compButtonBuilder(icon: Resource, text: string, callback: () => void) { Button() { Row({ space: 10 }) { Image(icon) .width(25) .height(25) .fillColor(Color.White) Text(text) .fontSize(25) .fontColor(Color.White) } } .width(120) .height(50) .onClick(callback) } } -
全局使用:请看具体案例
@Entry @Component struct Index { build() { // 外壳容器 Column({ space: 20 }) { Row({ space: 50 }) { // UI结构调用 globalButtonBuilder($r('app.media.ic_edit'), '编辑', () => console.log('编辑')) globalButtonBuilder($r('app.media.ic_share'), '发送', () => console.log('发送')) } } .width('100%') // 宽度撑满整个屏幕 .height('100%') // 高度撑满整个屏幕 .justifyContent(FlexAlign.Center) // 居中 } } // 全局UI结构复用 @Builder function globalButtonBuilder(icon: Resource, text: string, callback: () => void) { Button() { Row({ space: 10 }) { Image(icon) .width(25) .height(25) .fillColor(Color.White) Text(text) .fontSize(25) .fontColor(Color.White) } } .width(120) .height(50) .onClick(callback) } -
注意:
- 组件内的@Bulider方法要通过this调用,但是全局则不需要
- 组件内的@Bulider方法只能用于当前组件,全局的@Builder方法导出(export)导出,可用于整个应用
-
参数传递规则:
- 按值传递
- 按引用传递:当只有一个参数并且这个参数是对象的形式,优势是如果传递的参数包含了状态变量,则状态变量的变化会触发@Builder方法内部Ul的刷新
@Entry @Component struct Index { @State count: number = 0 build() { // 外壳容器 Column({ space: 50 }) { // 按值传递 valueTextBuilder(this.count) // 按引用传递 referenceTextBuilder({ count: this.count }) Row({ space: 50 }) { Button('-1') .onClick(() => { this.count-- }) Button('+1') .onClick(() => { this.count++ }) } } .width('100%') // 宽度撑满整个屏幕 .height('100%') // 高度撑满整个屏幕 .justifyContent(FlexAlign.Center) // 居中 } } @Builder function valueTextBuilder(count: number) { Text(`按值传递:${count}`) .fontSize(30) .fontWeight(FontWeight.Bold) } interface Obj { count: number } @Builder function referenceTextBuilder(obj: Obj) { Text(`按引用传递:${obj.count}`) .fontSize(30) .fontWeight(FontWeight.Bold) }
-
更多推荐



所有评论(0)