前几篇把四个基础组件讲完了,Text、Image、Button、TextInput。单个组件的用法,样式都应该熟悉了。
各种组件还需要组织才能成为实际的交互界面,ArkUI 怎么布局,有没有 CSS 一样的弹性布局?没学过 ArkUI 的肯定有这个疑问。
有。Column 和 Row,背后就是 Flex 弹性布局那套规则。写过 CSS 的 display: flex,这两个容器五分钟就能上手——只是换个写法,思路完全一样。没用过 Flex 也没关系,对齐方式、间距分配、弹性比例,这三件事搞清楚就够用了。
跟一些鸿蒙培训课程聊过,讲到布局这一章,有前端基础的学员基本扫一眼就过了,Column 和 Row 跟 CSS Flex 的对应关系太直接。没写过前端的多敲几个 demo 也能很快上手。
12.1 Column:竖直排列,就是 CSS 的 flex-direction: column
Column 把子组件从上到下排。
Column() { Text('第一行') Text('第二行') Text('第三行')}
三个 Text 竖着排。对应 CSS 写法:display: flex; flex-direction: column;。页面内容大部分都是这样从上往下堆的。
控制间距:space
CSS 里用 gap 控制子元素间距,鸿蒙用 space:
Column({ space: 12 }) { Text('第一行') Text('第二行') Text('第三行')}
space: 12,子组件之间隔 12 个 vp。比一个一个设 margin 省事。
主轴对齐:justifyContent
Column 的主轴是竖直方向。justifyContent 控制子组件在竖直方向上怎么分布,跟 CSS 的 justify-content 一样,取值也基本一致:
Column() { Text('第一行') Text('第二行')}.width('100%').height('100%').justifyContent(FlexAlign.Center)
CSS 里写 justify-content: center,鸿蒙写 .justifyContent(FlexAlign.Center)。对应关系:
| |
|---|
flex-start | FlexAlign.Start |
center | FlexAlign.Center |
flex-end | FlexAlign.End |
space-between | FlexAlign.SpaceBetween |
space-around | FlexAlign.SpaceAround |
交叉轴对齐:alignItems
Column 的交叉轴是水平方向。alignItems 控制子组件在水平方向上怎么对齐,对应 CSS 的 align-items:
Column() { Text('短') Text('这个比较长') Text('更长的一段文字')}.width('100%').alignItems(HorizontalAlign.Center)
HorizontalAlign.Center 让所有子组件水平居中,相当于 CSS 的 align-items: center。三个取值:HorizontalAlign.Start(左对齐)、HorizontalAlign.Center(居中)、HorizontalAlign.End(右对齐)。
CSS Flex 里 flex-direction: column 时,justify-content 管上下,align-items 管左右。Column 的规则完全一样——justifyContent 管竖直方向,alignItems 管水平方向。
12.2 Row:水平排列,就是 CSS 的 flex-direction: row
Row 把子组件从左到右排。
Row() { Text('左边') Text('中间') Text('右边')}
三个 Text 横着排,对应 CSS 的 display: flex; flex-direction: row;(默认值)。顶部导航栏、底部按钮组、文章卡片里作者和阅读量那行,都用 Row。
间距和对齐
Row 也有 space,跟 Column 一样:
Row({ space: 8 }) { Text('左边') Text('右边')}
Row 的主轴是水平方向,justifyContent 控制水平对齐:
Row() { Text('左') Text('右')}.width('100%').justifyContent(FlexAlign.SpaceBetween)
SpaceBetween 一个贴左一个贴右,中间空隙自动填充,对应 CSS 的 space-between。标题在左、更多按钮在右,就用这个。
Row 的交叉轴是竖直方向,alignItems 控制竖直对齐:
Row() { Text('小字') Text('大字')}.alignItems(VerticalAlign.Center)
两个 Text 字号不一样,VerticalAlign.Center 让它们在竖直方向上居中对齐,相当于 CSS 的 align-items: center。
Column 和 Row 的主轴交叉轴,跟 CSS Flex 的规则一模一样:
12.3 layoutWeight:弹性分配空间,就是 CSS 的 flex-grow
CSS 里用 flex-grow 让元素自动占满剩余空间。鸿蒙用 layoutWeight,作用一样。
Row() { Text('固定宽度') .width(100) .backgroundColor('#FFE0E0') Text('占满剩余空间') .layoutWeight(1) .backgroundColor('#E0E0FF')}.width('100%')
第一个 Text 占 100vp,第二个 Text 用 layoutWeight(1) 自动占满剩下的全部宽度。跟 CSS 的 flex-grow: 1 效果一样。
多个组件按比例分配:
Row() { Text('占一份') .layoutWeight(1) .backgroundColor('#FFE0E0') Text('占两份') .layoutWeight(2) .backgroundColor('#E0E0FF')}.width('100%')
一个 layoutWeight(1),一个 layoutWeight(2),宽度 1:2,跟 CSS 里分别设 flex-grow: 1 和 flex-grow: 2 一样。
layoutWeight 只有在父容器有明确尺寸时才生效。Row 的 width 得确定,Column 的 height 得确定。这个跟 CSS Flex 里 flex-grow 需要父容器有固定宽高才能计算剩余空间,是一样的前提。
12.4 实战:上中下三段式布局,CSS Flex 写法对比
把 Column、Row、layoutWeight 合在一起,做一个带顶部标题栏和底部按钮的页面。旁边标了对应的 CSS 写法:
@Entry@Componentstruct LayoutDemo { build() { Column() { // display: flex; flex-direction: column; height: 100%; // 顶部标题栏 Row() { // display: flex; flex-direction: row; Text('返回') .fontSize(16) .fontColor('#007DFF') Text('页面标题') .fontSize(18) .fontWeight(FontWeight.Medium) .layoutWeight(1) // flex-grow: 1; .textAlign(TextAlign.Center) Text('更多') .fontSize(16) .fontColor('#007DFF') } .width('100%') .height(48) .padding({ left: 16, right: 16 }) .backgroundColor('#F5F5F5') .alignItems(VerticalAlign.Center) // align-items: center; // 中间内容区,占满剩余空间 Column() { Text('内容区域') .fontSize(16) .fontColor('#999999') } .width('100%') .layoutWeight(1) // flex-grow: 1; .justifyContent(FlexAlign.Center) // justify-content: center; // 底部按钮 Button('确认') .width('90%') .height(48) .fontSize(16) .backgroundColor('#007DFF') .fontColor(Color.White) .borderRadius(24) .margin({ bottom: 20 }) } .width('100%') .height('100%') }}
顶部 Row 里三个元素:左边“返回”,中间标题用 layoutWeight 占满剩余空间居中对齐,右边“更多”。中间内容区用 Column 加 layoutWeight 撑满剩下高度,内容居中。底部一个固定按钮。上中下三段式布局,CSS Flex 和鸿蒙写法结构上一一对应。
12.5 需要注意的几个点
主轴和交叉轴的方向
Column 主轴竖直、交叉轴水平。Row 主轴水平、交叉轴竖直。justifyContent 管主轴,alignItems 管交叉轴。规则跟 CSS Flex 完全一样,写过 flex-direction: column 的话不用额外记。
space 和 margin 的区分
space 是容器统一给子组件之间设间距,对应 CSS 的 gap。margin 是单个组件自己的外边距。先统一用 space,个别需要特殊调整的再用 margin。
layoutWeight 需要父容器有尺寸
layoutWeight 在父容器没有明确宽高时不生效,跟 CSS flex-grow 需要父容器有固定尺寸才能计算剩余空间一个道理。Row 用它,Row 的 width 得确定;Column 用它,Column 的 height 得确定。
12.6 本篇总结
写过 CSS Flex 的话,鸿蒙的 Column 和 Row 就是换个写法:
Column = flex-direction: column
Row = flex-direction: row
justifyContent = justify-content
alignItems = align-items
space = gap
layoutWeight = flex-grow
没用过 Flex 也不影响,记住三件事:Column 竖排、Row 横排;justifyContent 管主轴对齐、alignItems 管交叉轴对齐;layoutWeight 弹性分配剩余空间。
一些鸿蒙培训课程讲布局,前端转过来的学员扫一遍文档就开始做页面了,概念全部对得上。没写过前端的多敲几个 demo 也能很快上手,Flex 布局本身不复杂。
常见问题
Q: Column 和 Row 的区别是什么?A: Column 竖直排列,对应 CSS flex-direction: column;Row 水平排列,对应 flex-direction: row。
Q: justifyContent 和 alignItems 有什么区别?A: justifyContent 管主轴方向的对齐,alignItems 管交叉轴方向的对齐。Column 里 justifyContent 管上下、alignItems 管左右;Row 里反过来。和 CSS 的 justify-content、align-items 规则一样。
Q: layoutWeight 和 flex-grow 是一回事吗?A: 一回事。都是分配父容器剩余空间的比例。layoutWeight(1) 对应 flex-grow: 1,layoutWeight(2) 对应 flex-grow: 2。
Q: space 和 margin 什么时候用哪个?A: space 是父容器给所有子组件统一设间距,对应 CSS 的 gap。margin 是单个组件自己的外边距。先统一用 space,个别需要特殊调整的再用 margin。
下一篇:Flex 布局能排整齐了,但不同屏幕尺寸下布局可能还是乱。下一篇讲响应式尺寸——vp 和 fp 是什么,百分比尺寸怎么用,横屏竖屏切换时布局怎么自动调整。
本文由「华鸿技术栈」原创发布,专注鸿蒙原生应用与元服务开发。分享实战代码、源码解析、性能优化及生态前沿。不讲虚的,只上干货。转载请联系授权。
#鸿蒙开发 #ArkTS #ArkUI #Flex布局 #Column #Row #鸿蒙原生应用开发