本节目标
· 掌握 ArkUI 常用基础组件(Text、Image、Button、TextInput、List)的核心属性与用法
· 掌握 Column、Row、Flex、Stack 四大布局容器的适用场景与对齐控制方法
· 理解主轴与交叉轴的概念,能够使用 justifyContent 与 alignItems 精准控制布局
· 掌握 stateStyles 多态样式,能够为组件设置正常态、按压态、禁用态等不同状态下的样式
· 理解响应式布局的核心思想,掌握断点系统与媒体查询的基本用法
· 能够综合运用组件、布局与样式,独立完成一个完整的 UI 页面开发
一、ArkUI 组件体系概览
1.1 组件的分类
ArkUI 的组件体系可以按功能分为以下几类:
基础组件:负责展示或交互,如 Text(文本)、Image(图片)、Button(按钮)、TextInput(文本输入框)、Slider(滑动条)等。
容器组件:负责组织子组件的排列方式,如 Column(垂直排列)、Row(水平排列)、Stack(层叠排列)、Flex(弹性布局)、List(列表)、Grid(网格)等。
媒体组件:处理视频、音频等多媒体内容,如 Video、Audio。
导航组件:处理页面间的跳转与导航,如 Navigation、Tabs、Swiper。
1.2 组件的通用属性
所有组件都支持一组通用属性,包括:
· 尺寸:.width()、.height()、.size()
· 边距与内边距:.margin()、.padding()
· 背景:.backgroundColor()、.backgroundImage()
· 边框:.border()、.borderRadius()
· 字体:.fontSize()、.fontColor()、.fontWeight()
· 布局:.layoutWeight()、.align()、.position()
· 多态样式:.stateStyles()
二、常用基础组件详解
2.1 Text 文本组件
Text 组件用于显示一段文本内容,支持富文本、字体样式、文本对齐等属性。
typescript
Text('Hello ArkUI')
.fontSize(24)
.fontColor('#333333')
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.lineHeight(32)
.letterSpacing(1)
核心属性:fontSize 设置字号,fontColor 设置颜色,fontWeight 设置字重,textAlign 设置水平对齐,maxLines 限制最大行数,textOverflow 设置溢出处理方式(省略号、裁剪等)。
富文本子组件:Text 可以包含 Span 子组件,实现不同样式的文本拼接:
typescript
Text() {
Span('¥').fontSize(14).fontColor(Color.Red)
Span('99').fontSize(24).fontColor(Color.Red).fontWeight(FontWeight.Bold)
Span(' 起').fontSize(12).fontColor('#999')
}
2.2 Image 图片组件
Image 组件用于展示图片,支持本地资源、网络图片和 PixelMap。
typescript
// 本地资源
Image($r('app.media.app_icon'))
.width(48)
.height(48)
.borderRadius(24)
.objectFit(ImageFit.Cover)
// 网络图片
Image('https://example.com/avatar.jpg')
.width(100)
.height(100)
.alt($r('app.media.placeholder')) // 加载失败时的占位图
核心属性:objectFit 控制图片缩放方式(Cover、Contain、Fill、None 等),alt 设置占位图,interpolation 设置插值方式。
2.3 Button 按钮组件
Button 组件是响应用户点击操作的核心交互组件,支持胶囊型、圆形和普通按钮三种类型。
typescript
// 胶囊按钮(默认)
Button('确认')
.type(ButtonType.Capsule)
.backgroundColor('#007DFF')
.fontColor(Color.White)
.width(120)
.height(40)
.onClick(() => {
console.info('按钮被点击')
})
// 带图标的按钮
Button() {
Row({ space: 6 }) {
Image($r('app.media.icon_share')).width(20).height(20)
Text('分享').fontSize(16).fontColor(Color.White)
}
}
.type(ButtonType.Capsule)
.backgroundColor('#007DFF')
.padding({ left: 20, right: 20 })
核心属性:type 设置按钮类型(Capsule、Circle、Normal),stateEffect 控制按压效果,onClick 绑定点击事件。
2.4 TextInput 文本输入组件
TextInput 是单行文本输入框,适用于用户名、搜索框等场景。
typescript
TextInput({ placeholder: '请输入用户名', text: this.username })
.width('100%')
.height(48)
.fontSize(16)
.placeholderColor('#999')
.backgroundColor('#F5F5F5')
.borderRadius(8)
.padding({ left: 16, right: 16 })
.maxLength(20)
.type(InputType.Normal) // Normal / Password / Email / Number
.onChange((value: string) => {
this.username = value
})
核心属性:placeholder 设置提示文字,text 设置初始值,maxLength 限制最大长度,type 设置输入类型,onChange 监听输入变化。
2.5 List 列表组件
List 是 ArkUI 中的列表容器组件,用于呈现连续、多行或多列的同类数据,支持垂直或水平滚动。
typescript
List({ space: 12 }) {
ForEach(this.messages, (msg: Message) => {
ListItem() {
Row({ space: 12 }) {
Image(msg.avatar).width(44).height(44).borderRadius(22)
Column({ space: 4 }) {
Text(msg.name).fontSize(16).fontWeight(FontWeight.Medium)
Text(msg.content).fontSize(14).fontColor('#666').maxLines(1)
}
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
}
.width('100%')
.padding(16)
}
}, (msg: Message) => msg.id.toString())
}
.width('100%')
.divider({ strokeWidth: 1, color: '#E5E5EA', startMargin: 72 })
核心属性:space 设置列表项间距,divider 设置分割线,scrollBar 控制滚动条显示。List 的子组件必须是 ListItem 或 ListItemGroup。
三、布局容器实战
3.1 布局的基本概念
ArkUI 的布局遵循约束、测量和放置的过程:父组件向子组件传递可用空间和尺寸约束,子组件根据内容计算自身大小,父组件按照布局规则确定子组件的位置。
主轴与交叉轴:每个布局容器都有一个主轴和一个交叉轴。Column 的主轴是垂直方向,交叉轴是水平方向;Row 的主轴是水平方向,交叉轴是垂直方向。
3.2 Column 垂直布局
Column 默认从上到下排列子组件,适合页面骨架、表单和纵向信息区。
typescript
Column({ space: 12 }) {
Text('Lulu').fontSize(22).fontWeight(FontWeight.Bold)
Text('HarmonyOS 应用开发者').fontSize(14).fontColor('#667085')
Button('编辑资料')
}
.width('100%')
.padding(20)
.alignItems(HorizontalAlign.Start)
.backgroundColor(Color.White)
.borderRadius(12)
space 用于设置相邻子组件之间的固定间距,比给每个组件分别添加 margin 更简洁。alignItems(HorizontalAlign.Start) 控制子组件在水平方向靠左对齐。
3.3 Row 水平布局
Row 从左到右排列子组件,适合头像与昵称、标题与操作按钮、工具栏等场景。
typescript
Row({ space: 12 }) {
Image($r('app.media.app_icon')).width(48).height(48).borderRadius(24)
Column({ space: 4 }) {
Text('张三').fontSize(16).fontWeight(FontWeight.Medium)
Text('在线').fontSize(13).fontColor('#34C759')
}
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
Button('关注')
.type(ButtonType.Capsule)
.backgroundColor('#007DFF')
.height(32)
}
.width('100%')
.padding(16)
3.4 Stack 层叠布局
Stack 容器中的子元素依次入栈,后一个子元素覆盖前一个子元素,子元素可以叠加,也可以设置位置。层叠布局适用于广告、卡片层叠、悬浮按钮等场景。
typescript
Stack({ alignContent: Alignment.BottomEnd }) {
Image($r('app.media.banner'))
.width('100%')
.height(200)
.borderRadius(12)
.objectFit(ImageFit.Cover)
Text('限时优惠')
.fontSize(14)
.fontColor(Color.White)
.backgroundColor(Color.Red)
.padding({ left: 10, right: 10, top: 5, bottom: 5 })
.borderRadius(4)
.margin(12)
}
.width('100%')
.height(200)
alignContent 控制子元素的对齐方式,支持九种对齐位置。
3.5 Flex 弹性布局
Flex 布局提供更加有效的方式对容器中的子元素进行排列、对齐和分配剩余空间。适用于需要动态伸缩和换行的场景。
typescript
Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.Start }) {
ForEach(this.tags, (tag: string) => {
Text(tag)
.fontSize(14)
.padding({ left: 12, right: 12, top: 6, bottom: 6 })
.backgroundColor('#F0F0F0')
.borderRadius(16)
.margin({ right: 8, bottom: 8 })
})
}
.width('100%')
四、多态样式 stateStyles
4.1 什么是多态样式
多态样式(stateStyles)可以依据组件的内部状态的不同,快速设置不同样式,类似于 CSS 伪类,但语法不同。ArkUI 提供六种状态:focused(获焦态)、normal(正常态)、pressed(按压态)、disabled(不可用态)、clicked(点击态)、selected(选中态)。
4.2 基本用法
typescript
Button('点击我')
.stateStyles({
normal: {
.backgroundColor('#007DFF')
.fontColor(Color.White)
},
pressed: {
.backgroundColor('#005BB5')
.scale({ x: 0.96, y: 0.96 })
},
disabled: {
.backgroundColor('#CCCCCC')
.fontColor('#999999')
}
})
.enabled(this.isEnabled)
.onClick(() => {
// 点击处理
})
4.3 事件冒泡与阻止
默认情况下,子组件的按压事件会冒泡到父组件,导致父组件的 stateStyles 也被触发。如果希望子组件改变时不影响父组件,可以在子组件绑定 onTouch 回调,并在回调中通过 stopPropagation 方法阻止事件传递。
typescript
@Component
struct ChildCard {
build() {
Column() {
Text('子组件内容')
}
.stateStyles({
pressed: {
.backgroundColor('#F7CE00')
},
normal: {
.backgroundColor('#50BE33')
}
})
.onTouch((event: TouchEvent) => {
event.stopPropagation() // 阻止冒泡到父组件
})
}
}
五、响应式布局入门
5.1 断点系统
HarmonyOS 提供断点系统用于适配手机、平板、折叠屏、PC 等不同设备形态。常用断点划分如下:
· sm(小屏) :320vp ≤ 宽度 < 520vp,对应手机竖屏
· md(中屏) :520vp ≤ 宽度 < 840vp,对应手机横屏、折叠屏展开态
· lg(大屏) :宽度 ≥ 840vp,对应平板、PC
5.2 媒体查询
使用 mediaquery 模块可以监听窗口尺寸变化,动态调整 UI 布局。
typescript
import { mediaquery } from '@kit.ArkUI';
@Entry
@Component
struct ResponsivePage {
@State currentBreakpoint: string = 'sm';
private listener: mediaquery.MediaQueryListener | null = null;
aboutToAppear(): void {
this.listener = mediaquery.matchMediaSync('(width>=840vp)');
this.listener.on('change', (result: mediaquery.MediaQueryResult) => {
this.currentBreakpoint = result.matches ? 'lg' : 'sm';
});
}
aboutToDisappear(): void {
this.listener?.off('change');
}
build() {
Column() {
if (this.currentBreakpoint === 'lg') {
// 大屏布局:分栏展示
Row() {
this.sidePanel()
this.mainContent()
}
} else {
// 小屏布局:单栏展示
Column() {
this.mainContent()
}
}
}
}
@Builder
sidePanel() {
Column().width(240).backgroundColor('#F5F5F5')
}
@Builder
mainContent() {
Column().layoutWeight(1).backgroundColor(Color.White)
}
}
六、综合实战:个人资料卡片
以下是一个综合运用组件、布局与样式的完整示例------个人资料卡片页面:
typescript
@Entry
@Component
struct ProfileCardPage {
@State isFollowed: boolean = false;
@State username: string = 'HarmonyOS 开发者';
build() {
Column({ space: 20 }) {
// 顶部卡片区域
Column({ space: 16 }) {
// 头像与基本信息(Row 布局)
Row({ space: 16 }) {
Image($r('app.media.avatar'))
.width(72).height(72).borderRadius(36)
.border({ width: 3, color: '#007DFF' })
Column({ space: 6 }) {
Text(this.username)
.fontSize(20).fontWeight(FontWeight.Bold)
Text('关注了 128 人 · 粉丝 1024')
.fontSize(13).fontColor('#666')
}
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
Button(this.isFollowed ? '已关注' : '关注')
.type(ButtonType.Capsule)
.backgroundColor(this.isFollowed ? '#E5E5EA' : '#007DFF')
.fontColor(this.isFollowed ? '#333' : Color.White)
.height(34)
.stateStyles({
pressed: { .scale({ x: 0.95, y: 0.95 }) }
})
.onClick(() => {
this.isFollowed = !this.isFollowed;
})
}
.width('100%')
// 个人简介(Text 组件)
Text('热爱 HarmonyOS 开发,专注于 ArkUI 界面与交互设计。')
.fontSize(14).fontColor('#444').lineHeight(22)
.maxLines(3).textOverflow({ overflow: TextOverflow.Ellipsis })
}
.width('100%')
.padding(20)
.backgroundColor(Color.White)
.borderRadius(16)
.shadow({ radius: 12, color: '#10000000', offsetY: 4 })
// 标签区域(Flex 换行布局)
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(['ArkUI', 'ArkTS', 'HarmonyOS', 'UI设计', '前端开发'], (tag: string) => {
Text(tag)
.fontSize(13)
.padding({ left: 14, right: 14, top: 6, bottom: 6 })
.backgroundColor('#F0F5FF')
.fontColor('#007DFF')
.borderRadius(16)
.margin({ right: 8, bottom: 8 })
})
}
.width('100%')
// 数据统计(Row 等分布局)
Row() {
this.statItem('动态', '56')
Divider().vertical(true).height(32).color('#E5E5EA')
this.statItem('关注', '128')
Divider().vertical(true).height(32).color('#E5E5EA')
this.statItem('粉丝', '1024')
}
.width('100%')
.padding(20)
.backgroundColor(Color.White)
.borderRadius(16)
.justifyContent(FlexAlign.SpaceEvenly)
}
.width('100%')
.height('100%')
.padding(16)
.backgroundColor('#F5F7FA')
.alignItems(HorizontalAlign.Center)
}
@Builder
statItem(label: string, value: string) {
Column({ space: 6 }) {
Text(value).fontSize(20).fontWeight(FontWeight.Bold)
Text(label).fontSize(13).fontColor('#999')
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Center)
}
}
七、多元化习题
习题 1(判断题)
题目:在 ArkUI 中,Column 容器的主轴方向是水平方向,交叉轴方向是垂直方向。
答案:错误
解读:Column 容器默认从上到下排列子组件,其主轴是垂直方向,交叉轴是水平方向。Row 容器的主轴才是水平方向。
习题 2(单选题)
题目:以下哪个属性用于控制 Image 组件的图片缩放方式?
A. borderRadius
B. objectFit
C. interpolation
D. alt
答案:B
解读:objectFit 控制图片的缩放方式(Cover、Contain、Fill、None 等)。borderRadius 设置圆角,interpolation 设置插值方式,alt 设置加载失败时的占位图。
习题 3(多选题)
题目:关于 stateStyles 多态样式,以下说法正确的有(多选):
A. stateStyles 可以依据组件的内部状态设置不同样式
B. pressed 状态表示组件按压态
C. 子组件的按压事件默认不会冒泡到父组件
D. 可以在子组件中通过 stopPropagation 阻止事件冒泡
答案:A、B、D
解读:stateStyles 可以依据组件的内部状态(focused、normal、pressed、disabled 等)快速设置不同样式,选项 A 正确。pressed 表示组件按压态,选项 B 正确。默认情况下,子组件的按压事件会冒泡到父组件,导致父组件的 stateStyles 也被触发,选项 C 错误。可以在子组件中通过 stopPropagation 阻止事件冒泡,选项 D 正确。
习题 4(代码填空题)
题目:请补全以下代码,实现一个胶囊按钮,点击时缩小到 0.95 倍。
typescript
Button('点击我')
.type(ButtonType.Capsule)
.backgroundColor('#007DFF')
.______________({
pressed: {
.scale({ x: 0.95, y: 0.95 })
}
})
答案:stateStyles
解读:stateStyles 是属性方法,用于根据组件的内部状态设置不同样式。pressed 状态表示组件按压态,在其中设置 .scale({ x: 0.95, y: 0.95 }) 即可实现按压时缩小的效果。
习题 5(代码改错题)
题目:以下代码存在布局问题,请指出问题并修正。
typescript
Column() {
Text('标题').fontSize(20)
Text('内容').fontSize(14)
Text('底部').fontSize(12)
}
.height(200)
答案:Column 容器设置了固定高度 200,但三个 Text 组件默认在垂直方向靠上排列,底部区域没有利用起来。如果需要让内容在垂直方向均匀分布,应设置 justifyContent 属性:
typescript
Column() {
Text('标题').fontSize(20)
Text('内容').fontSize(14)
Text('底部').fontSize(12)
}
.height(200)
.justifyContent(FlexAlign.SpaceBetween)
.alignItems(HorizontalAlign.Center)
解读:当 Column 拥有多余的垂直空间时,可以通过 justifyContent 分配主轴空间。SpaceBetween 使子组件分别贴近容器顶部和底部,并在水平方向居中。
习题 6(简答题)
题目:简述 Column、Row、Stack 三种布局容器的适用场景及核心对齐控制方式。
答案:Column 容器沿垂直方向排列子组件,适合页面骨架、表单、纵向信息区。通过 justifyContent 控制主轴(垂直方向)对齐,通过 alignItems 控制交叉轴(水平方向)对齐。Row 容器沿水平方向排列子组件,适合头像与昵称、标题与操作按钮、工具栏等场景。通过 justifyContent 控制主轴(水平方向)对齐,通过 alignItems 控制交叉轴(垂直方向)对齐。Stack 容器中的子元素依次入栈,后一个覆盖前一个,适用于广告、卡片层叠、悬浮按钮等场景。通过 alignContent 控制子元素在容器中的对齐位置,支持九种对齐方式。
解读:三种布局容器各有侧重,实际开发中常常组合使用。例如用 Column 搭建页面骨架,内部用 Row 排列水平信息,再用 Stack 实现图片上的文字叠加。
八、本节知识点总结
组件体系
ArkUI 组件分为基础组件(Text、Image、Button、TextInput、List 等)、容器组件(Column、Row、Stack、Flex、List、Grid 等)、媒体组件和导航组件。所有组件共享通用属性,包括尺寸、边距、背景、边框、字体、布局和多态样式。
常用基础组件
Text 支持富文本 Span 子组件和溢出处理;Image 通过 objectFit 控制缩放方式;Button 支持 Capsule、Circle、Normal 三种类型;TextInput 通过 onChange 监听输入变化;List 的子组件必须是 ListItem。
布局容器
Column 垂直排列,主轴为垂直方向;Row 水平排列,主轴为水平方向;Stack 层叠排列,通过 alignContent 控制对齐;Flex 弹性布局,支持 FlexWrap.Wrap 自动换行。justifyContent 控制主轴对齐,alignItems 控制交叉轴对齐。
多态样式 stateStyles
根据组件内部状态(normal、pressed、disabled、focused、clicked、selected)设置不同样式。子组件的按压事件默认会冒泡到父组件,可通过 stopPropagation 阻止。
响应式布局
断点系统将设备宽度划分为 sm(<520vp)、md(520-840vp)、lg(≥840vp)三个区间。使用 mediaquery.matchMediaSync 监听窗口尺寸变化,根据断点切换不同布局。
综合实战
一个完整的页面开发需要综合运用组件(Text、Image、Button)、布局(Column、Row、Flex)、样式(圆角、阴影、间距)和多态反馈。合理使用 @Builder 抽取可复用 UI 片段可以提升代码可维护性。
下节预告
第16课将进入 ArkUI 导航与多页面应用的学习,涵盖 Navigation 组件的完整用法、Tab 选项卡与侧边栏布局、以及多页面应用的路由架构设计。