HarmonyOS ArkTS 弹性布局 Flex:从“能用”到“写顺手”的一篇笔记
你写 ArkUI 的时候,Row/Column 用着很舒服,但一碰到这些场景就开始别扭:
- 顶部导航要 均分、要 两端贴边、中间还要自动留空
- 一排标签要 自动换行(像“流式标签”那种)
- 宽度不够时,希望子组件能 压缩一点,而不是直接挤爆/换行混乱
这时候就轮到 Flex 上场了:它本质上还是“线性排列”,但在 对齐、分配剩余空间、换行 这些方面更灵活。腾讯云
1)先把 Flex 的“脑内模型”搭起来
Flex 容器里,永远记住两根轴:
- 主轴:子组件默认沿着它排队(方向由
direction决定) - 交叉轴:垂直于主轴,主要用来做“对齐”腾讯云
Flex 的参数(官方文档里就是这一串):
Flex(value?: {
direction?: FlexDirection,
justifyContent?: FlexAlign,
alignItems?: ItemAlign,
wrap?: FlexWrap,
alignContent?: FlexAlign
})
你可以把它理解成: direction 管方向 → justifyContent 管主轴排布 → alignItems 管交叉轴对齐 → wrap 管换不换行 → alignContent 管多行如何“整体摆放”
2)direction:决定“主轴朝哪儿走”
direction 控制子组件的排列方向(也就是主轴方向),常用就是这四个:腾讯云
Row:从左到右RowReverse:从右到左Column:从上到下ColumnReverse:从下到上
我自己写页面时的习惯: 一行按钮/导航 →
Row一列信息/表单 →Column反向(Reverse)一般只在“聊天气泡从右往左”这类特定视觉里用,别滥用。
3)justifyContent:主轴方向怎么“排队”
justifyContent 控制的是 主轴方向 的排布方式(和 Row/Column 的思想一致)。腾讯云+1
常见的几个你一定会反复用:
Start:靠主轴起点排Center:整体居中End:靠主轴终点排SpaceBetween:两端贴边,中间等间距(导航栏最爱)SpaceAround:每个子组件左右两侧都有间距SpaceEvenly:间距更“平均”(首尾到边缘也相等)腾讯云
例子:做一个“顶部导航均分”
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceBetween }) {
Text('关注')
Text('推荐')
Text('热榜')
}
.width('100%')
.padding({ left: 16, right: 16, top: 12, bottom: 12 })
写这种东西时,Flex 比 Row 更“顺手”的点在于:你会更自然地把它当成一个“分配空间的容器”。
4)alignItems:交叉轴怎么“对齐”
alignItems 控制的是 交叉轴对齐。它的枚举里常用的有:Start / Center / End / Stretch / BaseLine 等。腾讯云+1
我用得最多的其实就三个:
Start:贴交叉轴起点Center:交叉轴居中Stretch:把子组件在交叉轴方向“拉伸”到容器尺寸(做等高布局很方便)腾讯云
例子:一排不同高度的元素,强制垂直居中
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
Text('标题').fontSize(18)
Text('副标题').fontSize(12)
Button('操作')
}
.height(56)
.padding({ left: 16, right: 16 })
小提醒:如果你发现“怎么我设置了 alignItems 还不对齐”, 先检查:容器本身有没有明确高度。没有高度时,你的“居中”有时会看不出效果。
5)wrap:到底换不换行(流式标签就是它)
wrap 是 Flex 很实用的一点:它决定子组件是否换行。DEV Community
NoWrap(默认):不换行;如果子组件总宽度超过父容器,会发生压缩(看起来像“挤在一行”)DEV CommunityWrap:换行,下一行继续沿主轴方向排DEV CommunityWrapReverse:换行,但行的排列方向相反(用得少)DEV Community
例子:做一个“自动换行的标签墙”
Flex({ direction: FlexDirection.Row, wrap: FlexWrap.Wrap }) {
Text('HarmonyOS').padding(8).backgroundColor(0xFFEAF2FF).borderRadius(12)
Text('ArkTS').padding(8).backgroundColor(0xFFEAF2FF).borderRadius(12)
Text('Flex').padding(8).backgroundColor(0xFFEAF2FF).borderRadius(12)
Text('布局').padding(8).backgroundColor(0xFFEAF2FF).borderRadius(12)
Text('自适应').padding(8).backgroundColor(0xFFEAF2FF).borderRadius(12)
}
.width('100%')
.padding(16)
这种“标签流式布局”,Row/Column 写起来就很拧巴,而 Flex + Wrap 就是顺理成章。
6)alignContent:多行情况下,“每一行整体怎么摆”
当你 wrap: Wrap 之后,子组件会变成多行。 这时 alignItems 管的是每个子组件在交叉轴的对齐;而 alignContent 更像是在管:这些行作为整体怎么在容器里分布。腾讯云
你可以把它理解成“多行版的 justifyContent”。
7)一个很真实的细节:容器对齐 vs 子组件对齐(谁说了算)
在 Flex 里,容器可以设置交叉轴对齐;子组件也可以单独设置自己的交叉轴对齐,并且子组件优先级更高。DEV Community
这在实际页面里特别常见:
- 一行里大部分元素都垂直居中
- 但某一个小角标/辅助文字希望靠上
- 这时就不要硬拆布局,而是给那个子组件单独调对齐(比你再套一层容器干净)
8)什么时候我会优先用 Flex,而不是 Row/Column?
我自己的“经验规则”是:
- 纯粹的线性排布,没啥空间分配花活 → Row/Column(更轻、更直观)
- 涉及“剩余空间怎么分、均分、两端贴边、自动换行” → Flex(省很多嵌套)腾讯云+1