HarmonyOS ArkUI Column 与 Row 布局:justifyContent、alignItems 与 layoutWeight
系列:鸿蒙 HarmonyOS 6.1 新特性实战 · 第 46 篇
Column 和 Row 是 ArkUI 中最基础的两种线性布局容器,分别沿垂直和水平方向排列子组件。掌握justifyContent、alignItems和layoutWeight这三个核心属性,能解决日常开发中绝大多数的布局需求。本篇通过可运行的完整示例,系统讲解每个属性的含义与适用场景。
运行效果
初始状态(Column 默认 Start 对齐):
切换到 SpaceBetween 模式后,子元素均匀分布在两端之间:
Column 的主轴对齐:justifyContent
Column 的主轴是垂直方向,justifyContent控制子组件沿垂直方向的分布方式。ArkUI 提供了六种FlexAlign值:
| 枚举值 | 效果 |
|---|---|
FlexAlign.Start | 子组件紧靠顶部(默认) |
FlexAlign.Center | 子组件整体居中 |
FlexAlign.End | 子组件紧靠底部 |
FlexAlign.SpaceBetween | 首尾紧贴边缘,其余均分间距 |
FlexAlign.SpaceAround | 每个子组件两侧各有相等的边距 |
FlexAlign.SpaceEvenly | 所有间距(含首尾)完全相等 |
// Column justifyContent 示例 Column() { Text('A') .width('80%').height(40) .backgroundColor('#e8f0ff') .textAlign(TextAlign.Center) Text('B') .width('80%').height(40) .backgroundColor('#b3d1ff') .textAlign(TextAlign.Center) Text('C') .width('80%').height(40) .backgroundColor('#6699ff') .fontColor('#fff') .textAlign(TextAlign.Center) } .width('100%').height(200) .justifyContent(FlexAlign.SpaceBetween) // 改成 SpaceAround / SpaceEvenly / Center / Start / End 观察差异SpaceBetween:A 顶部对齐,C 底部对齐,B 居中。SpaceAround:三个元素各自两侧间距相等,因此首尾有半个间距。SpaceEvenly:所有间距(含首尾)完全一致,视觉上最均匀。
Row 的交叉轴对齐:alignItems
Row 的主轴是水平方向,交叉轴是垂直方向,alignItems控制子组件在垂直方向的对齐。当子组件高度不同时,效果尤为明显:
// Row alignItems 示例:子组件高度各不相同 Row({ space: 8 }) { Text('Top') .height(40) .backgroundColor('#e8f0ff') .padding(8) Text('Center\n两行') .height(80) .backgroundColor('#b3d1ff') .padding(8) Text('Bottom') .height(60) .backgroundColor('#6699ff') .fontColor('#fff') .padding(8) } .width('100%') .alignItems(VerticalAlign.Center) // Top / Center / BottomVerticalAlign.Top使所有子组件顶部对齐;Center使它们垂直居中;Bottom使底部对齐。同理,Column 的alignItems接受HorizontalAlign.Start/Center/End,控制子组件在水平方向的对齐。
layoutWeight:按比例分配剩余空间
当需要让子组件按比例瓜分父容器的剩余空间时,使用layoutWeight。设置了该属性后,组件自身的width(在 Row 中)或height(在 Column 中)会被忽略,由权重值决定最终尺寸。
// 1:2:1 比例分配横向空间 Row() { Text('1') .layoutWeight(1) .height(44) .backgroundColor('#e8f0ff') .textAlign(TextAlign.Center) Text('2') .layoutWeight(2) .height(44) .backgroundColor('#0066ff') .fontColor('#fff') .textAlign(TextAlign.Center) Text('1') .layoutWeight(1) .height(44) .backgroundColor('#e8f0ff') .textAlign(TextAlign.Center) } .width('100%')三个 Text 的权重比为 1:2:1,中间元素占父容器宽度的一半,两端各占四分之一。若父容器宽度为 360vp,则分别为 90vp、180vp、90vp。
space 参数 vs padding/margin
Column 和 Row 都支持构造参数{ space: number },用于在相邻子组件之间插入统一间距,首个子组件前和最后一个子组件后不产生额外间距:
// space 参数:仅在子组件之间添加间距 Column({ space: 12 }) { Text('第一行').width('80%').height(40).backgroundColor('#e8f0ff').textAlign(TextAlign.Center) Text('第二行').width('80%').height(40).backgroundColor('#b3d1ff').textAlign(TextAlign.Center) Text('第三行').width('80%').height(40).backgroundColor('#6699ff').fontColor('#fff').textAlign(TextAlign.Center) } .width('100%').padding({ top: 16, bottom: 16, left: 16, right: 16 }) // padding 控制容器内边距,space 控制子组件间距,两者各司其职space与justifyContent: SpaceEvenly的区别:space是固定像素值,首尾无间距;SpaceEvenly是自适应均分,首尾也有相等间距。
完整代码
import { FlexAlign, VerticalAlign, HorizontalAlign } from '@ohos.arkui.common' @Entry @Component struct ColumnRowDemo { @State alignMode: FlexAlign = FlexAlign.Start private modes: FlexAlign[] = [ FlexAlign.Start, FlexAlign.Center, FlexAlign.End, FlexAlign.SpaceBetween, FlexAlign.SpaceAround, FlexAlign.SpaceEvenly ] private modeNames: string[] = [ 'Start', 'Center', 'End', 'SpaceBetween', 'SpaceAround', 'SpaceEvenly' ] @State modeIndex: number = 0 build() { Column({ space: 24 }) { // 标题 Text('Column justifyContent 演示') .fontSize(16).fontWeight(FontWeight.Bold).fontColor('#1a1a1a') // justifyContent 演示区 Column() { Text('A') .width('80%').height(40) .backgroundColor('#e8f0ff').textAlign(TextAlign.Center) Text('B') .width('80%').height(40) .backgroundColor('#b3d1ff').textAlign(TextAlign.Center) Text('C') .width('80%').height(40) .backgroundColor('#6699ff').fontColor('#fff').textAlign(TextAlign.Center) } .width('100%').height(200) .backgroundColor('#f8f9ff').borderRadius(8) .justifyContent(this.alignMode) // 当前模式标签 Text('当前模式:' + this.modeNames[this.modeIndex]) .fontSize(13).fontColor('#666') // 切换按钮 Button('切换 justifyContent') .width('60%').height(40) .onClick(() => { this.modeIndex = (this.modeIndex + 1) % this.modes.length this.alignMode = this.modes[this.modeIndex] }) Divider().strokeWidth(1).color('#e0e0e0') // Row alignItems 演示 Text('Row alignItems 演示(高度各异)') .fontSize(16).fontWeight(FontWeight.Bold).fontColor('#1a1a1a') Row({ space: 8 }) { Text('Top') .height(40).backgroundColor('#e8f0ff').padding(8) Text('Center\n两行') .height(80).backgroundColor('#b3d1ff').padding(8) Text('Bottom') .height(60).backgroundColor('#6699ff').fontColor('#fff').padding(8) } .width('100%').alignItems(VerticalAlign.Center) .backgroundColor('#f8f9ff').borderRadius(8).padding(8) Divider().strokeWidth(1).color('#e0e0e0') // layoutWeight 演示 Text('layoutWeight 1:2:1 比例分配') .fontSize(16).fontWeight(FontWeight.Bold).fontColor('#1a1a1a') Row() { Text('1') .layoutWeight(1).height(44) .backgroundColor('#e8f0ff').textAlign(TextAlign.Center) Text('2') .layoutWeight(2).height(44) .backgroundColor('#0066ff').fontColor('#fff').textAlign(TextAlign.Center) Text('1') .layoutWeight(1).height(44) .backgroundColor('#e8f0ff').textAlign(TextAlign.Center) } .width('100%') } .width('100%').padding(16) .backgroundColor('#ffffff') } }API 速查
| 属性/方法 | 说明 |
|---|---|
Column({ space: number }) | 设置子组件之间的垂直间距(不含首尾) |
Row({ space: number }) | 设置子组件之间的水平间距(不含首尾) |
.justifyContent(FlexAlign) | 控制主轴方向的子组件分布方式 |
.alignItems(VerticalAlign) | Row 中控制交叉轴(垂直)对齐 |
.alignItems(HorizontalAlign) | Column 中控制交叉轴(水平)对齐 |
FlexAlign.Start | 主轴起始方向靠齐 |
FlexAlign.SpaceBetween | 首尾贴边,其余均分间距 |
FlexAlign.SpaceAround | 每个元素两侧各有等量外边距 |
FlexAlign.SpaceEvenly | 所有间距(含首尾)完全相等 |
.layoutWeight(number) | 按权重比例分配主轴剩余空间,忽略自身 width/height |
小结
justifyContent控制主轴方向的分布(Column=垂直,Row=水平),六种 FlexAlign 值各有适用场景alignItems控制交叉轴方向的对齐(Column=水平,Row=垂直),子组件高度不同时效果最明显space参数在子组件之间插入固定间距,首尾不受影响,与justifyContent可以同时使用layoutWeight忽略组件在主轴方向的自身尺寸,按权重分配剩余空间,实现弹性比例布局- SpaceBetween 首尾贴边;SpaceAround 两侧各有半间距;SpaceEvenly 所有间距完全一致
- 简单线性排列优先用 Column/Row,复杂换行或双轴控制场景再考虑 Flex
上一篇:Toast、AlertDialog 与 CustomDialog 弹窗全解 | 下一篇:Flex 弹性布局完全指南
