鸿蒙布局终极指南:四大布局一次搞懂
本文是鸿蒙NEXT开发实战系列的第12篇,详细介绍了鸿蒙ArkUI提供的6种核心布局容器及其应用场景。主要内容包括:1) Column垂直布局和Row水平布局的基本用法;2) Stack层叠布局实现叠加效果;3) RelativeContainer相对布局处理复杂定位;4) Flex弹性布局支持响应式设计;5) Grid网格布局构建矩阵界面。文章通过代码示例展示了每种布局的特点和适用场景,并提供了
系列文章:鸿蒙NEXT开发实战系列 -- 第12篇 适合人群:鸿蒙开发初学者 开发环境:DevEco Studio 5.0.5+ | HarmonyOS NEXT (API 14) 阅读时长:约25分钟
引言:6种布局方式总览
布局是UI开发的基石,决定了界面元素的排列方式和空间分配。鸿蒙ArkUI提供了6种核心布局容器,覆盖从简单到复杂的各种界面需求:
|
布局容器 |
排列方式 |
典型场景 |
|---|---|---|
|
Column |
垂直线性排列 |
表单、列表项、垂直导航 |
|
Row |
水平线性排列 |
工具栏、标签页、水平卡片 |
|
Stack |
层叠重叠排列 |
轮播图、角标、悬浮按钮 |
|
RelativeContainer |
相对定位排列 |
复杂表单、不规则布局 |
|
Flex |
弹性盒子排列 |
响应式布局、自适应排列 |
|
Grid |
网格排列 |
图片墙、仪表盘、矩阵布局 |
掌握这6种布局,你就能实现任何复杂的界面设计。下面逐一详解。
1. 线性布局 Column(垂直排列)
功能说明
Column是垂直方向的线性布局容器,子组件从上到下依次排列。这是最基础、最常用的布局之一。
核心属性
|
属性 |
类型 |
说明 |
|---|---|---|
|
space |
string | number |
子组件间距 |
|
justifyContent |
FlexAlign |
垂直方向对齐方式 |
|
alignItems |
ItemAlign |
水平方向对齐方式 |
justifyContent可选值:Start(顶部)、Center(居中)、End(底部)、SpaceBetween(两端对齐)、SpaceAround(均匀分布)、SpaceEvenly(等间距)
alignItems可选值:Start(左对齐)、Center(居中)、End(右对齐)、Stretch(拉伸填满)
代码示例
@Entry
@Component
struct ColumnDemo {
build() {
Column({ space: 16 }) {
Text('Column布局示例')
.fontSize(24)
.fontWeight(FontWeight.Bold)
Text('第一项内容')
.width('100%')
.height(60)
.backgroundColor('#E3F2FD')
.textAlign(TextAlign.Center)
.borderRadius(8)
Text('第二项内容')
.width('100%')
.height(60)
.backgroundColor('#BBDEFB')
.textAlign(TextAlign.Center)
.borderRadius(8)
Text('第三项内容')
.width('100%')
.height(60)
.backgroundColor('#90CAF9')
.textAlign(TextAlign.Center)
.borderRadius(8)
}
.width('100%')
.height('100%')
.padding(16)
.justifyContent(FlexAlign.Center)
.alignItems(ItemAlign.Center)
}
}
适用场景
-
表单页面(登录、注册)
-
垂直列表项
-
设置页面
-
详情页内容区域
2. 线性布局 Row(水平排列)
功能说明
Row是水平方向的线性布局容器,子组件从左到右依次排列。常用于工具栏、导航栏等水平排列场景。
核心属性
|
属性 |
类型 |
说明 |
|---|---|---|
|
space |
string | number |
子组件间距 |
|
justifyContent |
FlexAlign |
水平方向对齐方式 |
|
alignItems |
ItemAlign |
垂直方向对齐方式 |
代码示例
@Entry
@Component
struct RowDemo {
build() {
Column({ space: 16 }) {
// 工具栏示例
Row({ space: 12 }) {
Button('返回')
.type(ButtonType.Normal)
.borderRadius(20)
Text('页面标题')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
.textAlign(TextAlign.Center)
Button('更多')
.type(ButtonType.Normal)
.borderRadius(20)
}
.width('100%')
.height(56)
.padding({ left: 16, right: 16 })
.backgroundColor('#F5F5F5')
.borderRadius(12)
// 标签页示例
Row({ space: 0 }) {
ForEach(['全部', '待付款', '待发货', '已完成'], (item: string) => {
Text(item)
.fontSize(14)
.layoutWeight(1)
.height(44)
.textAlign(TextAlign.Center)
.borderRadius({ bottomLeft: 8, bottomRight: 8 })
.backgroundColor(item === '全部' ? '#2196F3' : 'transparent')
.fontColor(item === '全部' ? '#FFFFFF' : '#666666')
})
}
.width('100%')
.backgroundColor('#FFFFFF')
}
.width('100%')
.height('100%')
.padding(16)
}
}
适用场景
-
顶部导航栏
-
底部TabBar
-
水平标签页
-
操作按钮组
3. 层叠布局 Stack(重叠排列)
功能说明
Stack是层叠布局容器,子组件按照添加顺序依次堆叠,后添加的组件显示在上层。适合实现叠加效果,如角标、遮罩层等。
核心属性
|
属性 |
类型 |
说明 |
|---|---|---|
|
alignContent |
Alignment |
子组件对齐方式 |
alignContent可选值:TopStart、Top、TopEnd、Start、Center、End、BottomStart、Bottom、BottomEnd
代码示例
@Entry
@Component
struct StackDemo {
build() {
Column({ space: 24 }) {
// 头像+角标示例
Stack({ alignContent: Alignment.BottomEnd }) {
Image($r('app.media.avatar'))
.width(80)
.height(80)
.borderRadius(40)
Text('3')
.fontSize(12)
.fontColor('#FFFFFF')
.backgroundColor('#FF4444')
.borderRadius(10)
.width(20)
.height(20)
.textAlign(TextAlign.Center)
.translate({ x: 4, y: 4 })
}
.width(88)
.height(88)
// 卡片+角标示例
Stack({ alignContent: Alignment.TopEnd }) {
Column() {
Text('商品名称')
.fontSize(18)
.fontWeight(FontWeight.Bold)
Text('¥99.00')
.fontSize(16)
.fontColor('#FF4444')
.margin({ top: 8 })
}
.width(200)
.height(120)
.backgroundColor('#FFFFFF')
.borderRadius(12)
.padding(16)
Text('HOT')
.fontSize(10)
.fontColor('#FFFFFF')
.backgroundColor('#FF6B00')
.borderRadius({ topLeft: 12, bottomLeft: 12 })
.padding({ left: 8, right: 8, top: 4, bottom: 4 })
}
}
.width('100%')
.height('100%')
.padding(16)
.justifyContent(FlexAlign.Center)
.alignItems(ItemAlign.Center)
}
}
适用场景
-
头像右上角消息角标
-
商品卡片促销标签
-
图片叠加文字水印
-
悬浮按钮覆盖内容
4. 相对布局 RelativeContainer
功能说明
RelativeContainer是相对布局容器,子组件可以相对于父容器或其他子组件进行定位。适合实现复杂的不规则布局。
核心属性
|
属性 |
类型 |
说明 |
|---|---|---|
|
alignRules |
AlignRuleOption |
相对对齐规则 |
对齐规则关键属性:
-
top/bottom/left/right:相对于目标组件的边 -
alignContentX/alignContentY:相对于父容器的对齐
代码示例
@Entry
@Component
struct RelativeContainerDemo {
build() {
RelativeContainer() {
// 左上角标题
Text('标题')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.id('title')
.alignRules({
top: { anchor: '__container__', align: VerticalAlign.Top },
left: { anchor: '__container__', align: HorizontalAlign.Start }
})
// 标题下方副标题
Text('副标题内容')
.fontSize(14)
.fontColor('#666666')
.id('subtitle')
.alignRules({
top: { anchor: 'title', align: VerticalAlign.Bottom },
left: { anchor: 'title', align: HorizontalAlign.Start }
})
// 右上角按钮
Button('编辑')
.id('editBtn')
.alignRules({
top: { anchor: '__container__', align: VerticalAlign.Top },
right: { anchor: '__container__', align: HorizontalAlign.End }
})
// 中间内容区域
Text('这里是主要内容区域,可以放置文章正文、图片等')
.fontSize(16)
.id('content')
.alignRules({
top: { anchor: 'subtitle', align: VerticalAlign.Bottom },
left: { anchor: '__container__', align: HorizontalAlign.Start },
right: { anchor: '__container__', align: HorizontalAlign.End }
})
.margin({ top: 16 })
}
.width('100%')
.height(300)
.padding(16)
.backgroundColor('#FAFAFA')
.borderRadius(12)
}
}
适用场景
-
复杂表单布局
-
不规则UI设计
-
需要精确定位的界面
-
多组件交叉依赖的场景
5. Flex弹性布局
功能说明
Flex布局是响应式设计的核心,通过主轴和交叉轴的概念,实现灵活的子组件排列和空间分配。相比Column/Row更加强大。
核心属性
|
属性 |
类型 |
说明 |
|---|---|---|
|
direction |
FlexDirection |
主轴方向 |
|
wrap |
FlexWrap |
是否换行 |
|
justifyContent |
FlexAlign |
主轴对齐方式 |
|
alignItems |
ItemAlign |
交叉轴对齐方式 |
|
alignContent |
FlexAlign |
多行交叉轴对齐 |
direction可选值:Row(水平)、Column(垂直)、RowReverse(水平反向)、ColumnReverse(垂直反向)
wrap可选值:NoWrap(不换行)、Wrap(换行)
代码示例
@Entry
@Component
struct FlexDemo {
build() {
Column({ space: 16 }) {
// 标签云示例
Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.Start, space: { main: LengthMetrics.vp(8), cross: LengthMetrics.vp(8) } }) {
ForEach(['鸿蒙', 'ArkUI', 'TypeScript', '移动开发', 'HarmonyOS', '前端', '跨平台'], (tag: string) => {
Text(tag)
.fontSize(14)
.fontColor('#1976D2')
.backgroundColor('#E3F2FD')
.borderRadius(16)
.padding({ left: 12, right: 12, top: 6, bottom: 6 })
})
}
.width('100%')
// 等分布局
Flex({ justifyContent: FlexAlign.SpaceEvenly }) {
ForEach(['首页', '发现', '消息', '我的'], (item: string, index: number) => {
Column() {
Text('icon')
.width(24)
.height(24)
.backgroundColor('#2196F3')
.borderRadius(12)
Text(item)
.fontSize(12)
.margin({ top: 4 })
}
})
}
.width('100%')
.height(60)
.backgroundColor('#FFFFFF')
.borderRadius(12)
}
.width('100%')
.height('100%')
.padding(16)
}
}
适用场景
-
标签云、流式布局
-
响应式自适应布局
-
底部导航栏
-
等分布局
6. Grid网格布局
功能说明
Grid是网格布局容器,通过定义行列将界面划分为均匀的网格单元,子组件可以占据一个或多个网格。适合实现矩阵式布局。
核心属性
|
属性 |
类型 |
说明 |
|---|---|---|
|
columnsTemplate |
string |
列定义模板 |
|
rowsTemplate |
string |
行定义模板 |
|
columnsGap |
Length |
列间距 |
|
rowsGap |
Length |
行间距 |
GridItem属性:
-
columnStart / columnEnd:占据列的起止位置
-
rowStart / rowEnd:占据行的起止位置
代码示例
@Entry
@Component
struct GridDemo {
build() {
Column({ space: 16 }) {
// 功能网格示例
Grid() {
ForEach([
{ name: '扫码', color: '#4CAF50' },
{ name: '付款', color: '#2196F3' },
{ name: '收款', color: '#FF9800' },
{ name: '转账', color: '#9C27B0' },
{ name: '理财', color: '#F44336' },
{ name: '保险', color: '#00BCD4' },
{ name: '信用', color: '#795548' },
{ name: '更多', color: '#607D8B' }
], (item: { name: string, color: string }) => {
Column() {
Text('icon')
.width(48)
.height(48)
.backgroundColor(item.color)
.borderRadius(24)
Text(item.name)
.fontSize(14)
.margin({ top: 8 })
}
.padding(16)
})
}
.columnsTemplate('1fr 1fr 1fr 1fr')
.rowsTemplate('1fr 1fr')
.columnsGap(8)
.rowsGap(8)
.width('100%')
.height(240)
.backgroundColor('#FFFFFF')
.borderRadius(12)
// 跨列布局示例
Grid() {
GridItem() {
Text('横幅广告')
.width('100%')
.height(80)
.backgroundColor('#FF5722')
.textAlign(TextAlign.Center)
.fontColor('#FFFFFF')
.fontSize(18)
.borderRadius(8)
}
.columnStart(0)
.columnEnd(3)
ForEach(['1', '2', '3'], (item: string) => {
GridItem() {
Text(item)
.width('100%')
.height(60)
.backgroundColor('#E3F2FD')
.textAlign(TextAlign.Center)
.borderRadius(8)
}
})
}
.columnsTemplate('1fr 1fr 1fr 1fr')
.rowsTemplate('auto auto')
.columnsGap(8)
.rowsGap(8)
.width('100%')
.height(160)
.backgroundColor('#FFFFFF')
.borderRadius(12)
}
.width('100%')
.height('100%')
.padding(16)
}
}
适用场景
-
九宫格功能入口
-
图片瀑布流
-
仪表盘数据展示
-
跨行跨列的复杂网格
布局选型决策表
|
布局类型 |
排列方向 |
换行支持 |
重叠支持 |
相对定位 |
适用场景 |
|---|---|---|---|---|---|
|
Column |
垂直 |
否 |
否 |
否 |
简单垂直排列 |
|
Row |
水平 |
否 |
否 |
否 |
简单水平排列 |
|
Stack |
层叠 |
- |
是 |
否 |
叠加效果 |
|
RelativeContainer |
任意 |
- |
否 |
是 |
复杂相对定位 |
|
Flex |
水平/垂直 |
是 |
否 |
否 |
响应式布局 |
|
Grid |
网格 |
- |
否 |
否 |
矩阵布局 |
选择建议:
-
简单垂直/水平排列 → Column/Row
-
需要叠加效果 → Stack
-
复杂相对定位 → RelativeContainer
-
需要换行或响应式 → Flex
-
矩阵/网格布局 → Grid
实战:用多种布局组合实现个人主页界面
下面通过一个完整的个人主页界面,展示如何组合使用多种布局:
@Entry
@Component
struct ProfilePage {
build() {
// Stack实现背景图+内容叠加
Stack({ alignContent: Alignment.Top }) {
// 背景图
Column()
.width('100%')
.height(200)
.linearGradient({
direction: GradientDirection.Bottom,
colors: [['#2196F3', 0.0], ['#1565C0', 1.0]]
})
// Column实现整体垂直排列
Column({ space: 16 }) {
// 头像区域 - Stack实现头像+角标叠加
Stack({ alignContent: Alignment.BottomEnd }) {
Image($r('app.media.avatar'))
.width(100)
.height(100)
.borderRadius(50)
.border({ width: 3, color: '#FFFFFF' })
Text('VIP')
.fontSize(10)
.fontColor('#FFFFFF')
.backgroundColor('#FF9800')
.borderRadius(8)
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
}
.margin({ top: 150 })
// 用户信息 - Column垂直排列
Column({ space: 4 }) {
Text('鸿蒙开发者')
.fontSize(24)
.fontWeight(FontWeight.Bold)
Text('专注HarmonyOS开发 | 分享技术干货')
.fontSize(14)
.fontColor('#666666')
}
// 数据统计 - Row水平等分
Row() {
ForEach([
{ label: '文章', value: '128' },
{ label: '粉丝', value: '5.2k' },
{ label: '获赞', value: '9.8k' }
], (item: { label: string, value: string }) => {
Column({ space: 4 }) {
Text(item.value)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#1976D2')
Text(item.label)
.fontSize(12)
.fontColor('#999999')
}
.layoutWeight(1)
.alignItems(ItemAlign.Center)
})
}
.width('100%')
.padding(16)
.backgroundColor('#FFFFFF')
.borderRadius(12)
// 标签云 - Flex弹性换行
Flex({ wrap: FlexWrap.Wrap, space: { main: LengthMetrics.vp(8), cross: LengthMetrics.vp(8) } }) {
ForEach(['ArkUI', 'TypeScript', '移动开发', 'HarmonyOS', '前端', '跨平台'], (tag: string) => {
Text(tag)
.fontSize(12)
.fontColor('#1976D2')
.backgroundColor('#E3F2FD')
.borderRadius(12)
.padding({ left: 10, right: 10, top: 4, bottom: 4 })
})
}
.width('100%')
// 功能网格 - Grid布局
Grid() {
ForEach([
{ icon: '📝', name: '我的文章' },
{ icon: '⭐', name: '我的收藏' },
{ icon: '📅', name: '我的日程' },
{ icon: '⚙️', name: '设置' }
], (item: { icon: string, name: string }) => {
Column({ space: 8 }) {
Text(item.icon)
.fontSize(28)
Text(item.name)
.fontSize(12)
.fontColor('#333333')
}
.padding(16)
})
}
.columnsTemplate('1fr 1fr 1fr 1fr')
.columnsGap(8)
.width('100%')
.backgroundColor('#FFFFFF')
.borderRadius(12)
}
.width('100%')
.height('100%')
.padding(16)
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
}
布局组合分析:
-
Stack:背景图与内容叠加
-
Column:整体垂直布局 + 子区域垂直排列
-
Row:数据统计水平等分
-
Stack:头像+VIP角标叠加
-
Flex:标签云弹性换行
-
Grid:功能入口网格布局
总结
鸿蒙ArkUI的6种布局各有特色,实际开发中往往需要组合使用:
|
布局 |
核心优势 |
学习优先级 |
|---|---|---|
|
Column/Row |
简单直观,最常用 |
★★★★★ |
|
Flex |
灵活强大,响应式 |
★★★★☆ |
|
Grid |
网格布局,跨行列 |
★★★★☆ |
|
Stack |
层叠效果,角标必备 |
★★★☆☆ |
|
RelativeContainer |
相对定位,复杂场景 |
★★★☆☆ |
实践建议:
-
优先使用Column/Row,能满足80%的布局需求
-
需要换行时考虑Flex
-
矩阵布局使用Grid
-
叠加效果使用Stack
-
复杂相对定位使用RelativeContainer
布局是UI开发的基础,熟练掌握这些布局容器,你就能轻松实现任何复杂的界面设计。建议多动手实践,通过实际项目加深理解。
下一篇预告:鸿蒙NEXT开发实战系列第13篇将讲解组件状态管理与数据绑定,敬请期待!
更多推荐



所有评论(0)