1. HarmonyOS 基础组件
1.1 Text 文本组件
Text(this.message)//文本内容
.width(200)
.height(50)
.margin({ top: 20, left: 20 })
.fontSize(30)//字体大小
.maxLines(1)// 最大行数
.textOverflow({ overflow: TextOverflow.Ellipsis })// 超出显示...
.fontColor(Color.Black)
.fontWeight(FontWeight.Bold)//字重:字体加粗
.onClick(() => {
this.clickCount++
})
.textAlign(TextAlign.Center)// 文本自身居中)
.lineHeight(30)//行高
// .textCase(TextCase.UpperCase)// 全大写
.textShadow({//设置阴影
radius: 5,
color: Color.Gray,
offsetX: 2,
offsetY: 2
})
.fontStyle(FontStyle.Normal)//字体样式
// .fontFamily($r('app.font.myfont'))//自定义字体(需在resources中添加字体文件)
// 富文本
Text(){
Span('点击次数: ').fontWeight(FontWeight.Bold)
Span(this.clickCount.toString()).fontColor('#FF0000')
}.margin({ top: 20, left: 20 })
// 装饰文本
Text('删除线示例')
.margin({ top: 20, left: 20 })
.decoration({
type: TextDecorationType.LineThrough,
// type: TextDecorationType.Underline, // 下划线
color: Color.Grey
})
1.2 Button 按钮组件
Button('属性介绍')
.width(120)// 宽度(单位vp)
.height(40)// 高度
.margin({ top: 10 })// 外边距
.padding(10) // 内边距
.border({//设置边框
width: 2,//边框宽度
color: '#FF0000',//边框颜色
radius: 8 // 圆角半径
})
.fontSize(16)//设置文本的大小
.fontColor('#FFFFFF')//文本的颜色
.fontWeight(FontWeight.Bold)//自重
.fontFamily('Arial')//字体
// .enabled(false)
// .opacity(0.5) // 透明度降低表示禁用
.backgroundColor(this.isPressed ? '#000000' : '#007DFF')
// .onTouch((e) => {
// this.isPressed = (e.type === TouchType.Down);
// })
.onClick(() => {
promptAction.showToast({
message: '文本带样式的按钮', duration: 1000 // 单位毫秒})
})
})
1.3 Image 图片组件
1.3.1 加载本地
Row() {
Text('加载本地:')
.margin({ top: 20 })
Image($r('app.media.ic_start_icon'))// resources目录下的图片
.margin({ top: 20, left: 20 })
.width(50)
.height(50)// 填充模式:
// - Cover(默认): 保持宽高比填满
// - Contain: 完整显示
// - Fill: 拉伸填满
// - ScaleDown: 自适应缩小
.objectFit(ImageFit.Cover)
}.alignItems(VerticalAlign.Top)
1.3.2 加载网络
Row() {
Text('加载网络:')
.margin({ top: 10 }) Image('https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png')
.margin({ top: 10, left: 20 })
.width(50)
.height(50)
.alt('加载失败')// 加载失败时显示图片或文字
.onComplete(() => {
console.log('图片加载完成');
})
.onError(() => {
console.log('图片加载失败');
})
.syncLoad(false) // 异步加载(默认)
}.alignItems(VerticalAlign.Top)
1.3.3 圆角和边框
Image($r('app.media.ic_start_icon'))// resources目录下的图片
.margin({ top: 20, left: 20 })
.width(40)
.height(40)// 填充模式:
.borderRadius(40)// 圆形效果
.border({
width: 2,
color: '#FF0000',
radius: 40 // 需与宽高一致
})
1.3.4 SVG加载使用的是Path
Row() {
Text('SVG图片:')
.margin({ top: 20 })
Path()
.margin({ top: 20, left: 20 })
.width(100)
.height(100)
.commands('M10 10 L90 10 L90 90 Z')// SVG路径数据
.fill('#FF0000')
}.alignItems(VerticalAlign.Top)
1.4 文本输入框
1.4.1 TextInput 单行文本输入框
@Entry
@Component
struct TextInputExample {
@State text: string = '' // 存储输入内容
build() {
Column() {
// 基础输入框
TextInput({ placeholder: '请输入用户名' })
.width('80%')
.height(50)
.margin(10)
.fontSize(16)
.onChange((value: string) => {
console.log(`输入内容:${value}`)
this.text = value // 更新状态变量
})
// 密码输入框
TextInput({ placeholder: '请输入密码' })
.type(InputType.Password) // 设置输入类型为密码
.width('80%')
.margin(10)
// 显示输入内容
Text(`当前输入:${this.text}`)
.margin(10)
}
.width('100%')
.padding(20)
}
}
1.4.2 TextArea 多行文本输入
适用于长文本场景。
@Entry
@Component
struct TextAreaExample {
@State longText: string = ''
build() {
Column() {
TextArea({ text: this.longText, placeholder: '请输入备注...' })
.width('90%')
.height(150)
.margin(10)
.onChange((value: string) => {
this.longText = value
})
Button('提交')
.onClick(() => {
console.log(`提交内容:${this.longText}`)
})
}
}
}
1.4.3 常用属性说明
1.4.3.1 **输入类型(type)**
- InputType.Normal:默认文本
- InputType.Number:数字键盘
- InputType.Number:数字键盘
- InputType.Number:数字键盘
1.4.3.2 事件监听
-
onChange(value: string)
:输入内容变化时触发 -
onSubmit()
:按下回车键时触发
1.4.3.3 代码示例
@Entry
@Component
struct LoginForm {
@State username: string = ''
@State password: string = ''
build() {
Column() {
TextField({ placeholder: '用户名' })
.width('80%')
.margin(10)
.onChange((value: string) => {
this.username = value
})
TextField({ placeholder: '密码' })
.type(InputType.Password)
.width('80%')
.margin(10)
.onChange((value: string) => {
this.password = value
})
Button('登录', { type: ButtonType.Capsule })
.width('50%')
.margin(20)
.onClick(() => {
if (this.username && this.password) {
// 执行登录逻辑
console.log(`登录信息:${this.username} / ${this.password}`)
}
})
}
.alignItems(HorizontalAlign.Center)
}
}
2. 常用的布局组件
2.1. 线性布局
Column(垂直布局) 和 Row(水平布局)
2.1.1 通用属性
Column和Row都支持以下通用属性:
属性 | 类型 | 说明 |
---|---|---|
width | Length | 设置组件宽度 |
height | Length | 设置组件高度 |
backgroundColor | Color | 设置背景颜色 |
padding | Padding | 设置内边距 |
margin | Margin | 设置外边距 |
border | BorderOptions | 设置边框 |
onClick | () => void | 点击事件 |
2.1.2 对齐方式枚举值
2.1.2.1 HorizontalAlign(水平对齐)
- Start:左对齐
- Center:居中对齐
- End:右对齐
2.1.2.2 VerticalAlign(垂直对齐)
- Top:顶部对齐
- Center:居中对齐
- Bottom:底部对齐
2.1.2.3 FlexAlign(主轴对齐)
- Start:起点对齐
- Center:居中对齐
- End:终点对齐
- SpaceBetween:两端对齐,项目间隔相等
- SpaceAround:每个项目两侧间隔相等
- SpaceEvenly:项目与项目、项目与边框间隔相等
2.1.3 代码示例
import { promptAction } from '@kit.ArkUI';
@Entry
@Component
struct ColumnAndRowPage {
@State message: string = 'Hello World';
build() {
Column({ space: 20 }) { // 子组件间距
// 子组件
this.columnLayout()
this.rowLayout()
this.columnLayoutBorder()
this.columnLayoutShadow()
this.columnLayoutComplexBorder()
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Start) // 垂直居中
.alignItems(HorizontalAlign.Start) // 水平居中
.backgroundColor('#F1F3F5')
}
@Builder
columnLayoutComplexBorder(){
Column() {
Text('花式边框').fontSize(20).margin(10)
Text('可以设置不同样式的边框').fontSize(16)
}
.width(300)
.height(100)
.border({
width: {
top: 3,
right: 1,
bottom: 3,
left: 1
},
color: {
top: '#3366FF',
right: '#3366FF',
bottom: '#3366FF',
left: '#3366FF'
},
radius: {
topLeft: 20,
topRight: 5,
bottomLeft: 5,
bottomRight: 20
},
style: BorderStyle.Dotted // 边框样式
})
.margin(10)
.padding(10)
.backgroundColor('#F5F5F5')
}
@Builder
columnLayoutBorder() {
Column({ space: 20 }) {
//
Text('带边框的布局').fontSize(20);
}
.height(100)
.width(300)
.justifyContent(FlexAlign.Start) // 垂直居中
.alignItems(HorizontalAlign.Start) // 水平居中
.backgroundColor('#F1F3F5')
.margin(10)
.padding(10)
.border({//设置边框
width: 2,
color:'#FF0000',
radius: 10
})
.shadow({
radius: 10,
color: '#888888',
offsetX: 2,
offsetY: 2
})
}
@Builder
columnLayoutShadow() {
Column({ space: 20 }) {
Text('带阴影的布局').fontSize(20);
}
.height(100)
.width(300)
.justifyContent(FlexAlign.Start) // 垂直居中
.alignItems(HorizontalAlign.Start) // 水平居中
.backgroundColor('#F1F3F5')
.margin(10)
.padding(10)
.border({//设置边框
width: 2,
color:'#FF0000',
radius: 10
})
.shadow({
radius: 10,
color: '#888888',
offsetX: 2,
offsetY: 2
})
}
@Builder
columnLayout() {
Column({ space: 20 }) {
//
Text('基础的Column').fontSize(20);
}
.height(50)
.width('100%')
.justifyContent(FlexAlign.Start) // 垂直居中
.alignItems(HorizontalAlign.Start) // 水平居中
.backgroundColor('#FFFFFF')
.margin(10)
.padding(10)
.onClick(() => {
promptAction.showToast({ message: '垂直布局点击' });
})
}
@Builder
rowLayout() {
Row({ space: 15 }) {
Text('Apple').fontSize(18)
Text('Banana').fontSize(18)
Text('Orange').fontSize(18)
}
.width(300)
.height(100)
.justifyContent(FlexAlign.SpaceBetween) // 两端对齐
.alignItems(VerticalAlign.Center) // 垂直居中
.backgroundColor('#EFF4FF')
.margin(10)
.padding(10)
.onClick(() => {
promptAction.showToast({ message: '水平布局点击' });
})
}
}
2.2 弹性布局 Flex
Flex 是 HarmonyOS 中强大的弹性布局组件,可以灵活地控制子元素的排列方式、对齐方式和空间分配。以下是 Flex 布局的完整使用示例。
特点:
-
通过
direction
设置主轴方向(Row/Column) -
通过
wrap
控制是否换行 -
适合需要自动调整的子元素布局
@Entry
@Component
struct FlexLayoutPage {
@State message: string = 'Hello World';build() { Column() { this.flexGrowLayout() this.flexBasisLayout() this.responsiveNavBar() this.cardLayout() }.height('100%') .width('100%') .backgroundColor('#F1F3F5') } /** * 卡片是布局 */ @Builder cardLayout() { Flex({ direction: FlexDirection.Row, wrap: FlexWrap.Wrap, justifyContent: FlexAlign.SpaceBetween }) { ForEach([1, 2, 3, 4, 5, 6], (item: number) => { Column() { Image($r('app.media.ic_start_icon')) .width(120) .height(120) .objectFit(ImageFit.Cover); Text('产品' + item) .margin({ top: 8 }); } .width(150) .height(150) .padding(10) .backgroundColor('#FFFFFF') .margin({ bottom: 15 }) .borderRadius(8) .shadow({ radius: 4, color: '#888888', offsetX: 2, offsetY: 2 }); }); } .width('100%') .padding(15) .backgroundColor('#F5F5F5') } /** * 水平权重的布局 */ @Builder flexGrowLayout() { Flex({ direction: FlexDirection.Row }) { Text('1').flexGrow(1).height(80).backgroundColor('#FF6B81') Text('2').flexGrow(3).height(80).backgroundColor('#FF9770') Text('3').flexGrow(1).height(80).backgroundColor('#FFD670') }.margin(10) .width('100%') .padding(10) .backgroundColor('#F5F5F5') } @Builder flexBasisLayout() { Flex({ direction: FlexDirection.Row }) { Text('1').flexBasis('20%').height(80).backgroundColor('#FF6B81') Text('2').flexBasis('30%').height(80).backgroundColor('#FF9770') Text('3').flexBasis('50%').height(80).backgroundColor('#FFD670') } .margin(10) .width('100%') .padding(10) .backgroundColor('#F5F5F5') } /** * 导航栏 */ @Builder responsiveNavBar() { Flex({ direction: FlexDirection.Row }) { Text('Logo').fontSize(20).fontWeight(FontWeight.Bold).flexShrink(0) Blank() // 空白填充 Flex({ direction: FlexDirection.Row }) { Text('首页').margin({ right: 15 }) Text('产品').margin({ right: 15 }) Text('关于').margin({ right: 15 }) Text('联系') } .displayPriority(1) // 优先显示 Button('登录').margin({ left: 15 }).flexShrink(0) } .width('100%') .padding(10) .margin(10) .backgroundColor('#FFFFFF') .border({ width: 1, color: '#E0E0E0' }) }
}
2.3 层叠布局 Stack
@Entry
@Component
struct StackLayoutPage {
build() {
Stack() {
Image($r('app.media.banner_pic1')) // 底层
Text('标题').align(Alignment.Top) // 顶层
}
.width('100%')
.height(200)
}
}
2.4 相对布局 RelativeContainer
@Entry
@Component
struct RelativeContainerPage {
@State message: string = 'Hello World';
build() {
RelativeContainer() {
Text('标题')
.alignRules({
top: { anchor: '__container__', align: VerticalAlign.Top },
left: { anchor: '__container__', align: HorizontalAlign.Start }
})
.id('title')
Button('确定')
.alignRules({
bottom: { anchor: '__container__', align: VerticalAlign.Bottom },
right: { anchor: '__container__', align: HorizontalAlign.End }
})
}
.height('100%')
.width('100%')
}
}
2.5 网格布局 Grid
@Entry
@Component
struct GridLayoutPage {
private items: string[] = ['苹果', '香蕉', '橙子', '西瓜', '葡萄', '芒果', '菠萝']
build() {
Grid() {
ForEach(this.items, (item: string) => {
GridItem() {
Text(item)
}
})
}
.margin(20)
.columnsTemplate('1fr 1fr 1fr') // 3等分列
.rowsTemplate('100px 100px') // 固定行高
.columnsGap(10) // 列间距
.rowsGap(15) // 行间
}
}
2.6 列表布局 List
List 是 HarmonyOS 中用于展示长列表数据的高性能组件,支持垂直滚动、分隔线、滚动条等功能。以下是 List 组件的完整使用示例。
2.6.1 List 常用属性与方法
属性/方法 | 类型 | 说明 |
---|---|---|
divider | DividerStyle | 设置分隔线样式 |
scrollBar | BarState | 滚动条状态(On/Off/Auto) |
edgeEffect | EdgeEffect | 滚动边缘效果(Spring/None) |
editMode | boolean | 是否开启编辑模式 |
stickyHeader | boolean | 分组标题是否吸顶 |
onScroll | (scrollOffset: number, scrollState: ScrollState) => void | 滚动事件回调 |
onReachStart/onReachEnd | () => void | 到达列表开始/结束回调 |
onItemDelete | (index: number) => boolean | 删除项目回调 |
onItemMove | (from: number, to: number) => boolean | 项目移动回调 |
2.6.2 代码示例
import TestBean from '../bean/TestBean';
@Entry
@Component
struct ListLayoutPage {
// 正确写法
@State bean: TestBean[] = [
new TestBean(1, '会议通知', '今天下午3点项目评审会', '10:30'),
new TestBean(2, '系统更新', '新版本v2.1.0已发布', '昨天'),
new TestBean(3, '日程提醒', '明天是张经理的生日', '周一')
];
private data: string[] = ['苹果', '香蕉', '橙子', '西瓜', '葡萄', '芒果', '菠萝']
private books: string[] = [
'HarmonyOS应用开发指南',
'TypeScript入门与实践',
'深入浅出OpenHarmony',
'ArkUI框架解析',
'分布式应用开发'
]
build() {
List({ space: 5 }) {
ForEach(this.bean, (item: TestBean) => {
ListItem() {
Column() {
Row() {
Text(item.title)
.fontSize(18)
.fontWeight(FontWeight.Bold)
Blank() // 空白填充
Text(item.time)
.fontSize(14)
.fontColor('#999999')
}
.width('100%')
Text(item.content)
.fontSize(16)
.margin({ top: 8 })
.width('100%')
}
.padding(15)
}
.borderRadius(8)
.margin({ top: 5, bottom: 5 })
.backgroundColor('#FFFFFF')
}, (item: TestBean) => item.id.toString())
}
.width('100%')
.height('100%')
.backgroundColor('#F7F8FA')
}
/**
* 基础的
*/
@Builder
BasicListExample() {
List({ space: 10 }) {
ForEach(this.data, (item: string) => {
ListItem() {
Text(item)
.fontSize(18)
.width('100%')
.height(50)
.textAlign(TextAlign.Center)
.backgroundColor('#FFFFFF')
}
}, (item: string) => item)
}
.margin({ top: 40 })
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
/**
* 带分割线的
*/
@Builder
ListWithDividerExample() {
List({ space: 5 }) {
ForEach(this.books, (book: string) => {
ListItem() {
Text(book)
.fontSize(16)
.padding(15)
}
})
}
.divider({
strokeWidth: 1,
color: '#E0E0E0',
startMargin: 15,
endMargin: 15
})
.scrollBar(BarState.On) // 显示滚动条
}
/**
* 复杂列表项示例
*/
@Builder
complexListItemExample() {
List({ space: 5 }) {
ForEach(this.bean, (item: TestBean) => {
ListItem() {
Column() {
Row() {
Text(item.title)
.fontSize(18)
.fontWeight(FontWeight.Bold)
Blank() // 空白填充
Text(item.time)
.fontSize(14)
.fontColor('#999999')
}
.width('100%')
Text(item.content)
.fontSize(16)
.margin({ top: 8 })
.width('100%')
}
.padding(15)
}
.borderRadius(8)
.margin({ top: 5, bottom: 5 })
.backgroundColor('#FFFFFF')
}, (item: TestBean) => item.id.toString())
}
.width('100%')
.height('100%')
.backgroundColor('#F7F8FA')
}
}
2.7 自适应布局 GridRow/GridCol
tItem() {
Column() {
Row() {
Text(item.title)
.fontSize(18)
.fontWeight(FontWeight.Bold)
Blank() // 空白填充
Text(item.time)
.fontSize(14)
.fontColor('#999999')
}
.width('100%')
Text(item.content)
.fontSize(16)
.margin({ top: 8 })
.width('100%')
}
.padding(15)
}
.borderRadius(8)
.margin({ top: 5, bottom: 5 })
.backgroundColor('#FFFFFF')
}, (item: TestBean) => item.id.toString())
}
.width('100%')
.height('100%')
.backgroundColor('#F7F8FA')
}
}
## 2.7 自适应布局 GridRow/GridCol