鸿蒙 Next 布局开发实战:6 大核心布局组件全解析
在鸿蒙 Next 开发中,布局是 UI 设计的骨架,直接决定了应用的视觉呈现与用户体验。ArkUI 框架提供了六种核心布局组件,覆盖了从简单排列到复杂多端适配的几乎所有场景。本文将从基础用法到实战技巧,手把手带你吃透线性布局、层叠布局、弹性布局、相对布局、栅格布局和选项卡,让你布局开发效率翻倍。
一、线性布局(Row/Column):最基础的 "排列能手"
线性布局是鸿蒙开发中最常用的布局方式,通过 Row(水平排列)和 Column(垂直排列)组件,能快速实现元素的线性排布。它就像搭积木时的 "横排" 和 "竖排",简单直接却能解决 80% 的基础布局需求。
1. 核心用法:主轴与交叉轴的 "双向控制"
线性布局的核心是对 "主轴" 和 "交叉轴" 的控制。以 Row 为例,主轴是水平方向,交叉轴是垂直方向;Column 则相反,主轴为垂直方向,交叉轴为水平方向。通过两个关键属性可精准控制子组件排列:
- justifyContent:控制子组件在主轴上的对齐方式(如居中、两端对齐等)
- alignItems:控制子组件在交叉轴上的对齐方式
代码示例:底部导航栏实现
scss
Row() {
// 首页按钮
Column() {
Image($r('app.media.ic_home'))
.width(24)
.height(24)
Text('首页')
.fontSize(12)
.marginTop(2)
}
.width('33%')
.alignItems(HorizontalAlign.Center) // 交叉轴居中
// 分类按钮
Column() {
Image($r('app.media.ic_category'))
.width(24)
.height(24)
Text('分类')
.fontSize(12)
.marginTop(2)
}
.width('33%')
.alignItems(HorizontalAlign.Center)
// 我的按钮
Column() {
Image($r('app.media.ic_mine'))
.width(24)
.height(24)
Text('我的')
.fontSize(12)
.marginTop(2)
}
.width('33%')
.alignItems(HorizontalAlign.Center)
}
.height(56)
.backgroundColor('#FFFFFF')
.shadow({ radius: 2, color: '#00000010' }) // 底部阴影
.justifyContent(FlexAlign.SpaceAround) // 主轴均匀分布
效果解析:这个底部导航栏通过 Row 的justifyContent(FlexAlign.SpaceAround)让三个按钮均匀分布,每个按钮内部用 Column 垂直排列图标和文字,整体结构清晰,适配各种屏幕宽度。
2. 高级技巧:flexWeight 实现 "比例分配"
当需要子组件按比例占据空间时,flexWeight属性是关键。它类似 CSS 中的 flex-grow,通过设置权重值让子组件按比例分配父容器的剩余空间(需注意:父容器必须指定主轴方向的尺寸,如 Row 需设 width,Column 需设 height)。
代码示例:登录页输入框布局
scss
Column() {
// 账号输入行
Row() {
Text('账号:')
.fontSize(16)
.flexWeight(1) // 占1份宽度
TextInput()
.hint('请输入账号')
.flexWeight(3) // 占3份宽度
.backgroundColor('#F5F5F5')
.borderRadius(4)
.padding({ left: 12 })
}
.height(48)
.margin({ left: 20, right: 20, top: 10 })
// 密码输入行
Row() {
Text('密码:')
.fontSize(16)
.flexWeight(1)
TextInput({ type: InputType.Password })
.hint('请输入密码')
.flexWeight(3)
.backgroundColor('#F5F5F5')
.borderRadius(4)
.padding({ left: 12 })
}
.height(48)
.margin({ left: 20, right: 20, top: 10 })
}
效果解析:通过flexWeight将 "账号:"" 密码:" 文本与输入框的宽度比例设为 1:3,无论屏幕宽窄,输入框始终占据更大部分空间,既保证美观又提升输入体验。
3. 避坑指南:别踩这些 "线性布局坑"
- 子组件溢出:当子组件总宽(高)超过父容器时,可通过constraintSize限制子组件最大尺寸,如constraintSize({ maxWidth: '100%' })
- 嵌套过深:线性布局嵌套别超过 3 层(如 Row 嵌套 Column 再嵌套 Row),否则会影响渲染性能,复杂布局可结合其他布局组件
- 忘记设尺寸:使用flexWeight时必须给父组件设主轴尺寸(如 Row 设 width: '100%'),否则权重分配无效
二、层叠布局(Stack):元素 "叠加显示" 的利器
当需要实现 "元素覆盖" 效果时,层叠布局(Stack)是最佳选择。它能让多个子组件按添加顺序层叠排列,就像一张张透明胶片叠在一起,适合实现图片水印、弹窗遮罩、徽章提示等场景。
1. 核心用法:定位与层叠顺序控制
Stack 的核心能力是 "定位" 和 "层级管理":
- position:设置子组件绝对定位(相对于 Stack 容器),如position({ x: 10, y: 10 })表示距离容器左上角 x=10vp、y=10vp
- zIndex:控制子组件层叠顺序,数值越大越靠上(默认按添加顺序,后添加的在上面)
- alignContent:控制所有子组件在 Stack 中的整体对齐方式(如居中、右下角等)
代码示例:商品图片水印效果
scss
Stack() {
// 主图
Image($r('app.media.goods_img'))
.width('100%')
.height(200)
.objectFit(ImageFit.Cover) // 保持比例裁剪
// 折扣标签(左上角)
Text('限时7折')
.backgroundColor('#FF3B30')
.color('#FFFFFF')
.fontSize(12)
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.borderRadius(2)
.position({ x: 12, y: 12 }) // 左上角定位
.zIndex(1) // 确保在图片上方
// 新品标签(右上角)
Text('新品')
.backgroundColor('#007AFF')
.color('#FFFFFF')
.fontSize(12)
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.borderRadius(2)
.position({ x: '90%', y: 12 }) // 右上角定位(右距10%)
.zIndex(1)
}
.width('100%')
.height(200)
.clip(true) // 超出容器部分裁剪
效果解析:通过 Stack 将商品主图、折扣标签、新品标签层叠,两个标签用position分别固定在左上角和右上角,zIndex确保标签在图片上方,实现了电商常见的商品标签效果。
2. 实战场景:弹窗组件的实现
Stack 最典型的实战场景是 "弹窗"------ 遮罩层 + 弹窗内容的组合。通过控制弹窗组件的显示 / 隐藏,可快速实现交互效果。
代码示例:基础弹窗组件
scss
Stack() {
// 底层内容(页面正常内容)
Column() {
Text('点击按钮显示弹窗')
Button('打开弹窗')
.marginTop(20)
.onClick(() => {
this.showDialog = true // 控制弹窗显示
})
}
// 弹窗(条件显示)
if (this.showDialog) {
Stack() {
// 遮罩层(半透明黑色)
Text('')
.backgroundColor('#00000070')
.width('100%')
.height('100%')
.onClick(() => {
this.showDialog = false // 点击遮罩关闭
})
// 弹窗内容
Column() {
Text('提示')
.fontSize(18)
.fontWeight(FontWeight.Bold)
Text('这是一个用Stack实现的弹窗')
.fontSize(14)
.margin({ top: 10, bottom: 20 })
Button('确定')
.width(120)
.onClick(() => {
this.showDialog = false
})
}
.width(280)
.backgroundColor('#FFFFFF')
.borderRadius(8)
.padding(20)
.alignItems(HorizontalAlign.Center)
.position({ x: '50%', y: '50%' }) // 居中定位
.offset({ x: -140, y: -80 }) // 偏移自身一半尺寸实现居中
}
}
}
效果解析:弹窗由 "遮罩层" 和 "内容区" 组成,通过showDialog状态控制显示。遮罩层占满全屏(半透明),内容区用position+offset实现居中,点击遮罩或确定按钮可关闭弹窗,符合用户交互习惯。
3. 避坑指南:层叠布局的 "注意事项"
- 定位基准:position的 x/y 值是相对于 Stack 容器的左上角,若要实现 "右下角" 定位,可结合offset或计算 x/y 值(如 x = 容器宽 - 组件宽 - 边距)
- 性能优化:隐藏的子组件(如弹窗)建议用if条件渲染,而非visibility,可减少渲染开销
- 容器尺寸:Stack 默认尺寸由子组件决定,若需占满父容器,需显式设置width('100%')和height('100%')
三、弹性布局(Flex):动态内容的 "自适应高手"
弹性布局(Flex)是处理 "动态内容" 的利器 ------ 当子组件数量不固定(如标签流、商品列表),或需要根据屏幕尺寸自动调整排列时,Flex 能通过 "自动换行" 和 "弹性伸缩" 特性,让布局自适应各种场景。
1. 核心用法:换行与弹性系数
Flex 的核心属性集中在 "换行控制" 和 "伸缩控制":
- wrap:控制子组件是否换行,FlexWrap.Wrap为自动换行(超出父容器时换行),FlexWrap.NoWrap为不换行(默认,子组件会被压缩)
- flexGrow:子组件的 "扩张系数",空间充足时按比例分配剩余空间
- flexShrink:子组件的 "收缩系数",空间不足时按比例收缩
代码示例:自适应标签流
less
Flex({ direction: FlexDirection.Row, wrap: FlexWrap.Wrap }) {
// 动态标签列表(假设tags是从接口获取的数组)
ForEach(this.tags, (tag) => {
Text(tag)
.padding({ left: 12, right: 12, top: 6, bottom: 6 })
.backgroundColor('#F0F2F5')
.color('#333333')
.fontSize(14)
.borderRadius(20)
.margin({ right: 8, bottom: 8 }) // 标签间距
})
}
.width('100%')
.padding(12)
效果解析:通过wrap: FlexWrap.Wrap,标签会根据容器宽度自动换行 ------ 屏幕宽时一排显示多个,屏幕窄时自动折行,无需手动计算标签位置,完美适配动态标签场景(如商品属性标签、搜索历史标签)。
2. 实战场景:商品列表的灵活排布
电商商品列表是 Flex 的典型应用场景 ------ 商品数量不固定,且需要在不同屏幕尺寸下保持美观排列。
代码示例:电商商品列表
scss
Flex({ direction: FlexDirection.Row, wrap: FlexWrap.Wrap }) {
ForEach(this.goodsList, (goods) => {
// 商品卡片
Column() {
Image(goods.imgUrl)
.width('100%')
.height(160)
.objectFit(ImageFit.Cover)
Text(goods.name)
.fontSize(14)
.margin({ top: 8, left: 8, right: 8 })
.lines(2) // 最多2行
.textOverflow({ overflow: TextOverflow.Ellipsis }) // 超出省略
Text(`¥${goods.price}`)
.fontSize(16)
.color('#FF3B30')
.fontWeight(FontWeight.Bold)
.margin({ top: 4, left: 8, bottom: 8 })
}
.width('31%') // 每行3个(留间距)
.backgroundColor('#FFFFFF')
.borderRadius(8)
.margin({ left: '1.5%', top: 10 })
})
}
.backgroundColor('#F5F5F7')
.padding({ top: 10 })
效果解析:通过width('31%')和margin({ left: '1.5%' }),实现每行 3 个商品的排布(31%*3 + 1.5%*2 ≈ 100%),结合wrap: FlexWrap.Wrap自动换行,在手机、平板上都能保持整齐的排列,无需为不同设备单独写布局。
3. 避坑指南:Flex 的 "伸缩陷阱"
- 换行失效:若子组件设置了固定 width 且总和超过父容器,需确保wrap设为FlexWrap.Wrap,否则子组件会被强制压缩
- 尺寸异常:避免给 Flex 子组件设置flexGrow和固定 width 同时生效,可能导致尺寸计算混乱
- 对齐问题:多行文元素可通过alignContent调整整体对齐(如FlexAlign.Start顶对齐),避免行间距不一致
四、相对布局(RelativeContainer):组件 "关系定位" 的专家
相对布局(RelativeContainer)通过 "组件间的位置关系" 实现布局 ------ 子组件可相对于容器或其他子组件定位(如 "组件 A 在组件 B 的右边"),适合实现复杂的关联布局(如表单控件与提示文字的关联、不规则元素的排列)。
1. 核心用法:锚点规则与权重分配
RelativeContainer 的核心是 "锚点规则":通过alignRules属性为子组件设置 "锚点"(参考对象)和 "对齐方式",实现相对定位。鸿蒙 Next 还新增了chainWeight属性,支持按比例分配组件间距。
代码示例:表单控件与提示文字
less
RelativeContainer() {
// 输入框
TextInput()
.id('input') // 设id,供其他组件参考
.width(300)
.height(48)
.backgroundColor('#F5F5F5')
.borderRadius(4)
.padding({ left: 12 })
// 提示文字(输入框右侧)
Text('必填')
.id('tip')
.fontSize(12)
.color('#FF3B30')
.alignRules({
left: { anchor: 'input', align: HorizontalAlign.End }, // 左对齐输入框的右边缘
top: { anchor: 'input', align: VerticalAlign.Top }, // 上对齐输入框的上边缘
})
.margin({ left: 8 }) // 与输入框间距8vp
}
.alignRules({
'input': {
left: { anchor: '__container__', align: HorizontalAlign.Start }, // 输入框左对齐容器
top: { anchor: '__container__', align: VerticalAlign.Top }, // 输入框上对齐容器
}
})
.padding(20)
效果解析:提示文字通过alignRules设置 "左边缘对齐输入框的右边缘",无论输入框宽度如何变化,提示文字始终紧跟在输入框右侧,避免了固定定位在不同场景下的错位问题。
2. 高级技巧:chainWeight 实现比例布局
鸿蒙 Next 的chainWeight属性可实现 "链式布局"------ 多个组件按权重比例分配空间,类似线性布局的flexWeight,但更灵活(可跨组件关联)。
代码示例:1:2:1 比例布局
less
RelativeContainer() {
Text('左侧')
.id('left')
.backgroundColor('#E5E9F2')
.height(80)
.alignRules({
top: { anchor: '__container__', align: VerticalAlign.Top },
bottom: { anchor: '__container__', align: VerticalAlign.Bottom },
left: { anchor: '__container__', align: HorizontalAlign.Start },
})
Text('中间')
.id('center')
.backgroundColor('#C9CDD4')
.height(80)
.alignRules({
top: { anchor: 'left', align: VerticalAlign.Top },
bottom: { anchor: 'left', align: VerticalAlign.Bottom },
left: { anchor: 'left', align: HorizontalAlign.End },
})
Text('右侧')
.id('right')
.backgroundColor('#E5E9F2')
.height(80)
.alignRules({
top: { anchor: 'center', align: VerticalAlign.Top },
bottom: { anchor: 'center', align: VerticalAlign.Bottom },
left: { anchor: 'center', align: HorizontalAlign.End },
right: { anchor: '__container__', align: HorizontalAlign.End },
})
}
.chainWeights({ 'left': 1, 'center': 2, 'right': 1 }) // 权重1:2:1
.chainStyle(ChainStyle.SPREAD) // 均匀分配空间
.width('100%')
.height(80)
.padding(12)
效果解析:通过chainWeights设置三个组件的权重为 1:2:1,中间组件宽度是左右组件的 2 倍,且整体占满容器宽度,适合实现分栏布局(如首页的 "推荐 - 热点 - 关注" 三栏)。
3. 避坑指南:相对布局的 "关联陷阱"
- 循环依赖:避免组件 A 依赖组件 B,同时组件 B 依赖组件 A(如 "A 左对齐 B,B 右对齐 A"),会导致布局崩溃
- ID 遗漏:使用alignRules时,务必给参考组件设id,否则锚点无效
- 尺寸异常:若组件未设置固定尺寸且无锚点限制,可能会无限扩张,建议给关键组件设minWidth/maxWidth
五、栅格布局(GridRow/GridCol):多端适配的 "终极方案"
栅格布局(GridRow+GridCol)是鸿蒙 Next 为 "多端适配" 设计的布局方案 ------ 将屏幕划分为若干 "列",通过控制组件占有的 "列数",实现同一套代码在手机、平板、车机等不同设备上的自适应布局,真正做到 "一次开发,多端部署"。
1. 核心用法:断点与列数控制
栅格布局的核心是 "断点系统" 和 "列配置":
- 断点:鸿蒙默认将设备宽度分为 xs(<320vp)、sm(320-520vp)、md(520-840vp)、lg(>840vp)四类,对应手机、平板等设备
- columns:GridRow 通过columns设置不同断点下的总列数(默认 12 列)
- span:GridCol 通过span设置组件在不同断点下占据的列数
代码示例:响应式栅格配置
php
GridRow({
columns: { xs: 4, sm: 6, md: 8, lg: 12 }, // 不同断点的总列数
gutter: { xs: 5, sm: 10, md: 15, lg: 20 } // 不同断点的列间距
}) {
// 组件1:小屏占2列,大屏占3列
GridCol({ span: { xs: 2, sm: 2, md: 2, lg: 3 } }) {
Text('组件1')
.width('100%')
.height(80)
.backgroundColor('#E5E9F2')
.textAlign(TextAlign.Center)
}
// 组件2:小屏占2列,大屏占3列
GridCol({ span: { xs: 2, sm: 2, md: 2, lg: 3 } }) {
Text('组件2')
.width('100%')
.height(80)
.backgroundColor('#C9CDD4')
.textAlign(TextAlign.Center)
}
// 组件3:小屏占4列(满行),大屏占6列
GridCol({ span: { xs: 4, sm: 6, md: 8, lg: 6 } }) {
Text('组件3')
.width('100%')
.height(80)
.backgroundColor('#9CA3AF')
.textAlign(TextAlign.Center)
}
}
.width('100%')
.padding(12)
效果解析:在手机(xs 断点,总列数 4)上,组件 1 和 2 各占 2 列(一行 2 个),组件 3 占 4 列(满行);在平板(lg 断点,总列数 12)上,组件 1 和 2 各占 3 列,组件 3 占 6 列,布局自动适配设备尺寸,无需写多套布局代码。
2. 实战场景:新闻资讯页的多端适配
新闻资讯类应用需要在不同设备上展示不同的内容密度 ------ 手机上单列紧凑排布,平板上多列展示更多内容,栅格布局能完美解决这个问题。
代码示例:新闻资讯页布局
scss
GridRow() {
// 头条新闻(全宽)
GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
Column() {
Image($r('app.media.news_head'))
.width('100%')
.height(200)
.objectFit(ImageFit.Cover)
Text('鸿蒙Next发布,全新布局系统详解')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ top: 10 })
}
.padding(10)
}
// 次要新闻(小屏单列,大屏多列)
ForEach(this.newsList, (news) => {
GridCol({ span: { xs: 12, sm: 12, md: 6, lg: 4 } }) {
Column() {
Image(news.imgUrl)
.width('100%')
.height(120)
.objectFit(ImageFit.Cover)
Text(news.title)
.fontSize(14)
.margin({ top: 8 })
.lines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.padding(10)
.backgroundColor('#FFFFFF')
.borderRadius(8)
}
})
}
.backgroundColor('#F5F5F7')
效果解析:头条新闻在所有设备上都占满行(span:12);次要新闻在手机(xs/sm 断点)上占满行(1 列),在平板(md 断点)上每行 2 列,在大屏设备(lg 断点)上每行 3 列,内容密度随设备变化,兼顾阅读体验和空间利用率。
3. 避坑指南:栅格布局的 "适配要点"
- 断点选择:根据目标设备设置断点,若需适配手表等小屏设备,可自定义 xs 断点值(如 < 200vp)
- 列数规划:建议默认用 12 列布局(主流设计系统通用),便于计算比例(如 3 列占 1/4,6 列占 1/2)
- 间距控制:通过gutter设置列间距,避免组件挤在一起,大屏建议更大间距(如 lg:20vp)
六、选项卡(Tabs):内容 "分区切换" 的高效工具
选项卡(Tabs)用于实现 "同一区域展示不同内容" 的场景 ------ 通过顶部 / 底部标签切换内容,既节省空间又保持内容关联性,适合首页分类切换、个人中心功能分区等场景。
1. 核心用法:标签与内容的关联
Tabs 由 "标签栏" 和 "内容区" 组成,核心属性包括:
- barPosition:标签栏位置(BarPosition.Top顶部 /BarPosition.Bottom底部)
- index:默认激活的标签索引(从 0 开始)
- swipeable:是否支持滑动切换内容区
- TabContent:单个标签对应的内容组件,第一个参数为标签文字
代码示例:基础选项卡
scss
Tabs({ barPosition: BarPosition.Top, index: 0 }) {
// 推荐标签
TabContent('推荐') {
List() {
ForEach(this.recommendList, (item) => {
ListItem() {
// 推荐内容项
Text(item.title)
.padding(12)
.width('100%')
}
})
}
}
// 热点标签
TabContent('热点') {
List() {
ForEach(this.hotList, (item) => {
ListItem() {
// 热点内容项
Text(item.title)
.padding(12)
.width('100%')
}
})
}
}
// 关注标签
TabContent('关注') {
List() {
ForEach(this.followList, (item) => {
ListItem() {
// 关注内容项
Text(item.title)
.padding(12)
.width('100%')
}
})
}
}
}
.barHeight(48) // 标签栏高度
.indicatorColor('#007AFF') // 指示器颜色
.indicatorHeight(3) // 指示器高度
.swipeable(true) // 支持滑动切换
.onChange((index) => {
console.log(`切换到标签:${index}`)
})
效果解析:顶部标签栏显示 "推荐"" 热点 ""关注",点击标签或滑动内容区可切换,indicatorColor设置蓝色指示器,swipeable支持滑动交互,符合主流应用的交互习惯。
2. 高级技巧:自定义标签样式
默认标签样式可能不符合设计需求,Tabs 支持通过builder自定义标签内容(如添加图标、修改样式)。
代码示例:带图标的自定义标签
less
Tabs() {
// 首页标签(自定义样式)
TabContent({
value: '首页',
builder: this.TabBuilder('首页', $r('app.media.ic_home'), 0)
}) {
// 首页内容
}
// 分类标签(自定义样式)
TabContent({
value: '分类',
builder: this.TabBuilder('分类', $r('app.media.ic_category'), 1)
}) {
// 分类内容
}
// 我的标签(自定义样式)
TabContent({
value: '我的',
builder: this.TabBuilder('我的', $r('app.media.ic_mine'), 2)
}) {
// 我的内容
}
}
.barPosition(BarPosition.Bottom)
.barHeight(56)
.backgroundColor('#FFFFFF')
.onChange((index) => {
this.activeIndex = index // 记录激活标签
})
// 自定义标签构建函数
@Builder TabBuilder(title: string, icon: Resource, index: number) {
Column() {
Image(icon)
.width(24)
.height(24)
.tintColor(this.activeIndex === index ? '#007AFF' : '#999999') // 激活态变色
Text(title)
.fontSize(12)
.marginTop(2)
.color(this.activeIndex === index ? '#007AFF' : '#999999')
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
效果解析:通过@Builder定义TabBuilder函数,实现 "图标 + 文字" 的标签样式,且激活标签(activeIndex)的图标和文字变为蓝色,非激活态为灰色,底部标签栏的视觉效果更丰富,适合作为应用的主导航。
3. 避坑指南:选项卡的 "性能与体验"
- 内容懒加载:TabContent 默认懒加载(首次切换时才渲染),若内容复杂可提前预加载,但会增加初始加载耗时
- 标签数量:标签数量建议≤5 个,超过时可改用 "滚动标签栏"(设置barMode: BarMode.Scrollable)
- 状态保存:切换标签时内容会重新渲染,若需保存状态(如表单输入内容),需手动用变量存储状态值
总结:6 大布局组件的 "场景选择指南"
掌握了六种布局组件后,关键是 "在合适的场景用对组件",这里整理了一份选择指南:
布局组件 | 核心优势 | 最佳适用场景 |
---|---|---|
线性布局(Row/Column) | 简单直接、性能高 | 基础排列(如列表项、按钮组、导航栏) |
层叠布局(Stack) | 支持元素覆盖、定位灵活 | 水印、弹窗、徽章、复杂视觉层次 |
弹性布局(Flex) | 自动换行、动态适配 | 标签流、商品列表、动态内容排布 |
相对布局(RelativeContainer) | 组件关联定位、比例分配 | 表单控件关联、不规则元素排列、比例布局 |
栅格布局(GridRow/GridCol) | 多端适配、响应式布局 | 跨设备应用(手机 / 平板 / 车机)、复杂页面框架 |
选项卡(Tabs) | 内容分区切换、节省空间 | 分类内容切换(如首页推荐 / 热点、个人中心) |
实际开发中,很少单一使用一种布局 ------ 通常是 "线性布局搭框架 + 弹性布局排列表 + 层叠布局做弹窗" 的组合。比如电商首页:用 Column 做整体垂直排列,顶部用 Stack 实现轮播图 + 倒计时,中间用 Flex 做分类标签,商品区用栅格布局适配多端,底部用选项卡切换 "推荐 / 热销"。
布局开发的核心是 "先拆结构,再选组件"------ 先将 UI 拆分为独立区块,再为每个区块选择最合适的布局组件,最后组合实现整体效果。多练几个实际页面(如登录页、商品详情页、首页),很快就能形成自己的布局思维!