Appearance
常用布局容器
ArkUI 提供 6 种核心布局容器,掌握它们的使用场景和嵌套规则。
1. 6 种布局容器总览
| 容器 | 布局方向 | 适用场景 | 关键特性 |
|---|---|---|---|
| Row | 水平排列 | 横排菜单、标签栏 | flex-wrap, justify-content |
| Column | 垂直排列 | 列表、表单、页面布局 | flex-wrap, justify-content |
| Stack | 层叠排列 | 图片叠加、悬浮按钮 | z-index、锚点定位 |
| Flex | 弹性排列 | 自适应布局、响应式 | flex-grow/shrink/basis |
| Grid | 网格排列 | 商品列表、相册 | 行列定义、自动填充 |
| RelativeContainer | 相对定位 | 复杂布局、锚点定位 | 锚点、相对定位 |
2. Row — 水平布局
2.1 基本用法
typescript
Row() {
Text('Item 1')
.padding(10)
Text('Item 2')
.padding(10)
Text('Item 3')
.padding(10)
}
.width('100%')
.justifyContent(FlexAlign.Start) // 对齐方式
.gap(10) // 间距2.2 常用属性
| 属性 | 说明 |
|---|---|
justifyContent | 水平方向对齐(Start/Center/End/SpaceAround/SpaceBetween) |
alignItems | 交叉轴对齐(Start/Center/End/Baseline) |
gap | 子元素间距 |
width/height | 容器尺寸 |
wrap | 是否换行(Wrap/NoWrap) |
3. Column — 垂直布局
3.1 基本用法
typescript
Column() {
Text('标题')
.fontSize(24)
.fontWeight(FontWeight.Bold)
Divider()
Text('内容')
.fontSize(16)
Button('按钮')
.width('100%')
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Start)
.gap(10)3.2 弹性布局子元素
typescript
Column() {
Text('固定内容')
.height(100)
// 空白填充,把内容推到最底部
Blank()
Text('底部内容')
.height(50)
}
.height('100%')💡 Blank 组件:在 Row 或 Column 中自动填充剩余空间,常用于"左边文字-右边图标"或"顶部内容-底部固定"的布局。
4. Stack — 层叠布局
4.1 基本用法
typescript
Stack() {
// 底层
Image('background.jpg')
.width('100%')
.height('200vp')
// 上层
Text('覆盖文字')
.fontSize(24)
.fontColor(Color.White)
.position({ x: 20, y: 20 })
}
.width('100%')
.height('200vp')4.2 Stack 的锚点定位
typescript
Stack() {
// 子元素可以通过 position 或 alignContent 定位
Image('icon')
.position({ x: '50%', y: '50%' }) // 中心定位
Text('Badge')
.position({ x: '80%', y: '10%' }) // 右上角
}
.width('200vp')
.height('200vp')4.3 适用场景
- 图片 + 文字覆盖
- 悬浮按钮(FAB)
- 头像 + 在线状态标记
- 视频封面 + 播放按钮
5. Flex — 弹性布局
5.1 基本用法
typescript
Flex() {
// flexGrow: 1 → 占据剩余空间的权重
Text('Item 1')
.flexGrow(1)
Text('Item 2')
.flexGrow(1)
// 固定宽度
Text('固定')
.width(100)
}
.width('100%')
.flexWrap(FlexWrap.Wrap) // 可换行
.mainAxisAlign(FlexAlign.Center) // 主轴对齐
.crossAxisAlign(CrossAxisAlign.Center) // 交叉轴对齐5.2 flexGrow / flexShrink / flexBasis
| 属性 | 说明 |
|---|---|
flexGrow | 分配剩余空间的比例 |
flexShrink | 空间不足时缩小比例 |
flexBasis | 初始尺寸 |
typescript
Flex() {
Text('A')
.flexGrow(2) // 占 2 份
.width(100)
Text('B')
.flexGrow(1) // 占 1 份
.width(100)
}
.width('100%')5.3 适用场景
- 自适应宽度的卡片列表
- 响应式导航栏
- 内容分配不均的布局
6. Grid — 网格布局
6.1 基本用法
typescript
Grid() {
GridItem() {
Text('1')
}
GridItem() {
Text('2')
}
GridItem() {
Text('3')
}
GridItem() {
Text('4')
}
}
.columnsTemplate('1fr 1fr 1fr') // 3 列等宽
.rowsTemplate('100vp 100vp') // 2 行
.gap(8)
.width('100%')6.2 网格模板
typescript
// 1fr = 1 fraction(等分剩余空间)
.columnsTemplate('1fr 2fr 1fr') // 4:2:1 的比例
.rowsTemplate('auto 1fr auto') // 第一行自动高度,中间撑满,最后一行自动6.3 适用场景
- 商品/照片列表
- 仪表盘
- 九宫格菜单
7. RelativeContainer — 相对布局 ⭐
7.1 解决的核心痛点
嵌套过深 → 减少布局层级 → 提升渲染性能
传统方式(嵌套深):
Column → Row → Stack → Image
→ Text
→ Button
→ Row → Text
相对布局(扁平):
RelativeContainer → Image(锚点A)
→ Text(锚点A)
→ Button(锚点B)7.2 基本用法
typescript
// 定义锚点
@Entry
@Component
struct Index {
build() {
RelativeContainer() {
// 定义锚点
Rect()
.id('anchor1')
.width(0)
.height(0)
.position({ x: 50, y: 50 })
// 图片:锚点 anchor1 的右下角
Image('icon.png')
.alignRules({
top: { anchor: 'anchor1', align: VerticalAlign.Top },
left: { anchor: 'anchor1', align: HorizontalAlign.Start }
})
.width(100)
.height(100)
// 文字:相对于图片的位置
Text('描述')
.alignRules({
top: { anchor: 'anchor1', align: VerticalAlign.Top },
right: { anchor: 'image', align: HorizontalAlign.End },
bottom: { anchor: 'image', align: VerticalAlign.Bottom }
})
}
.width('100%')
.height('100%')
}
}7.3 对齐方式
| 锚点对齐 | 说明 |
|---|---|
HorizontalAlign.Start | 左对齐 |
HorizontalAlign.End | 右对齐 |
HorizontalAlign.Center | 居中 |
VerticalAlign.Top | 顶对齐 |
VerticalAlign.Bottom | 底对齐 |
VerticalAlign.Middle | 垂直居中 |
7.4 适用场景
- 复杂商品卡片
- 相册照片叠加
- 地图标注
8. 布局容器嵌套规则
8.1 推荐嵌套方式
typescript
// 页面级:Column 或 Row 为主框架
Column() {
// 头部
Row() { ... }
// 内容
Stack() {
Image('banner')
Text('标题')
}
// 列表
List() { ... }
// 底部
Row() { ... }
}8.2 避免嵌套过深
typescript
// ❌ 嵌套超过 4 层,性能下降
Column() → Row() → Stack() → Column() → Text()
// ✅ 提取为子组件
@Component
struct Header { ... } // Row
@Component
struct Banner { ... } // Stack
build() {
Column() {
Header()
Banner()
List()
}
}9. 面试高频考点
Q1: 6 种布局容器分别是什么?各自适用什么场景?
回答:
- Row:水平排列,导航栏/标签
- Column:垂直排列,页面主框架/列表
- Stack:层叠排列,图片覆盖/悬浮元素
- Flex:弹性排列,自适应/响应式
- Grid:网格排列,商品列表/相册
- RelativeContainer:相对定位,复杂布局(解决嵌套过深问题)
Q2: RelativeContainer 解决了什么痛点?
回答:解决复杂布局中嵌套层级过深的问题。通过锚点(Anchor)定位,减少布局次数,提升渲染性能。
Q3: Blank 组件的作用?
回答:在 Row/Column 中自动填充剩余空间,常用于将两端组件推到边缘(如"左边文字-右边图标")或把内容推到屏幕底部。
🐱 小猫提示:6 种容器记住口诀:横排 Row,竖排 Column,层叠 Stack,弹性 Flex,网格 Grid,相对 RelativeContainer。面试直接报出这 6 个名字就够。