HarmonyOS ArkTS 弹性布局 Flex:从“能用”到“写顺手”的一篇笔记

56 阅读4分钟

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 Community
  • Wrap:换行,下一行继续沿主轴方向排DEV Community
  • WrapReverse:换行,但行的排列方向相反(用得少)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