鸿蒙开发3--UI布局(玩转鸿蒙的Row、Column与Stack容器)
在前两文中,我们已经掌握了怎么使用基础组件并通过@State来驱动UI更新。
但是,要从简单的按钮和文本进化到精美的用户界面,我们必须学会怎么组织和排列这些组件。
今天,我们聊一聊ArkUI中最核心的布局容器:Row、Column、Stack,以及强大的Flex弹性布局。
一、布局的本质
在ArkUI中,布局就是把一组UI组件(子组件)按照特定的规则放在一个容器(父组件)里。
选择哪种容器,就决定了他内部组件的排列方式。
可以想象成整理书架,你可以选择横着放、竖着放,或者把几本书叠在一起。
1.1. Column (垂直布局)
Column是我们最熟悉的布局容器之一,他会把所有的子组件从上到下垂直排列。
基础用法:
Column() {Text('用户登录').fontSize(24).fontWeight(FontWeight.Bold)TextInput({ placeholder: '请输入用户名' }).margin(10)TextInput({ placeholder: '请输入密码' }).margin(10)Button('登录').width(200).margin(10)}.width('100%').padding(20)
这个简单的登录表单就是Column的典型应用场景。
常用属性 (对齐方式): Column
内部的对齐是控制水平方向(交叉轴)的位置。
-
alignItems(HorizontalAlign)
:-
HorizontalAlign.Start
: 水平居左(默认)。 -
HorizontalAlign.Center
: 水平居中。 -
HorizontalAlign.End
: 水平居右。
-
Column() {// ...子组件}.width('100%').alignItems(HorizontalAlign.Center) // 让所有子组件水平居中
1.2. Row (水平布局)
跟Column相反,Row会把所有子组件从左到右水平排列。
基础用法:
Row() {Image($r('app.media.avatar')).width(60).height(60).borderRadius(30)Column() {Text('用户名').fontSize(18)Text('个性签名').fontSize(14).fontColor(Color.Gray)}.alignItems(HorizontalAlign.Start).margin({ left: 10 })}.padding(15).backgroundColor(Color.White).borderRadius(10)
这种左边头像、右边用户信息的结构,就比较适合用Row。
常用属性 (对齐方式): Row内部的对齐是控制垂直方向(交叉轴)的位置。
-
alignItems(VerticalAlign)
:-
VerticalAlign.Top
: 垂直居上。 -
VerticalAlign.Center
: 垂直居中(默认)。 -
VerticalAlign.Bottom
: 垂直居下。
-
1.3. Stack (层叠布局)
Stack的布局允许子组件像Photoshop的图层一样,一个接一个的在Z轴上堆叠起来。
后添加的组件会覆盖在先添加的组件之上。
基础用法:
Stack() {// 第一层:背景图Image($r('app.media.card_background')).width('100%').height(200)// 第二层:叠加在图片上的文字Text('新用户专属优惠券').fontColor(Color.White).fontSize(22)}.width(350).borderRadius(15)
在背景图上叠加文字、在视频上放置播放按钮等场景,最适合的就是Stack。
常用属性 (对齐方式): Stack的对齐同时控制水平和垂直方向。
-
alignContent(Alignment)
: 使用Alignment枚举值,可以精确定位子组件在9个方向的位置(如TopStart, Center, BottomEnd等)。默认是Alignment.Center。
1.4. Flex (弹性布局)
Flex是目前最强大、最灵活的布局方式,Row和Column实际上是Flex的特例。
他不仅能控制主轴方向(水平或垂直),还能管理空间分配、自动换行等复杂场景。
-
Flex({ direction: FlexDirection.Row })
等价于Row。 -
Flex({ direction: FlexDirection.Column })
等价于Column。
Flex的核心属性:
-
direction
: 主轴方向 (Row, Column, RowReverse, ColumnReverse)。 -
justifyContent
: 主轴上的对齐方式 (Start, Center, End, SpaceBetween, SpaceAround, SpaceEvenly)。 -
alignItems
: 交叉轴上的对齐方式 (Start, Center, End, Stretch)。 -
wrap
: 是否自动换行 (FlexWrap.Wrap, FlexWrap.NoWrap)。
当Row和Column的简单对齐无法满足需求时,比如需要实现两端对齐(SpaceBetween),就必须使用Flex。
二、搭建一个简单的个人名片
根据上面的布局暂时是,构建一个如下图所示的个人名片。
3.1准备
示例图中一共需要四张图片:
头像图标:avatar_icon.png
电话图标:phone_icon.png
邮箱图标:email_icon.png
地址图标:location_icon.png
这些png图片可以去https://www.iconfinder.com/下载。
2.2分析布局
最外层:整个名片是一个从上到下的结构,用Column。
顶部区域:头像、姓名、职位是水平排列的,用Row。
在Row内部,姓名和职位又是垂直排列的,所以需要一个嵌套的Column。
中间区域:分割线,一个简单的Divider组件。
底部区域:三个带图标的联系方式,是水平均匀分布的,用Flex布局最合适。
2.3创建模块
我们还是跟之前的计数器模块一样创建一个独立的模块。
上一步准备的图片资源放在新建模块resources/base/media目录下。
2.4代码实现
@Entry@Componentstruct Index {build() {// 1. 最外层:垂直布局Column() {// 2. 顶部区域:水平布局Row() {Image($r('app.media.avatar')).width(80).height(80).borderRadius(40)// 姓名和职位的垂直容器Column() {Text('懒惰蜗牛').fontSize(22).fontWeight(FontWeight.Bold)Text('鸿蒙应用开发工程师').fontSize(16).fontColor(Color.Gray).margin({ top: 5 })}.alignItems(HorizontalAlign.Start) // 文字左对齐.margin({ left: 15 })}.width('100%').padding(20)// 3. 分割线Divider().strokeWidth(1).color('#f1f1f1').margin({ top: 10 })// 4. 底部联系方式:弹性布局实现均匀分布Flex({ justifyContent: FlexAlign.SpaceAround, alignItems: ItemAlign.Center }) {// 电话Column() {Image($r('app.media.phone_icon')).width(24).height(24)Text('电话').fontSize(14).margin({ top: 5 })}// 邮箱Column() {Image($r('app.media.email_icon')).width(24).height(24)Text('邮箱').fontSize(14).margin({ top: 5 })}// 地址Column() {Image($r('app.media.location_icon')).width(24).height(24)Text('地址').fontSize(14).margin({ top: 5 })}}.width('100%').height(100)}.width(350).backgroundColor(Color.White).borderRadius(15).shadow({ radius: 10, color: '#dddddd' }).padding(10)}}
总结
今天,我们学习了ArkUI布局的四大金刚:
-
Column:垂直线性布局。
-
Row:水平线性布局。
-
Stack:层叠覆盖布局。
-
Flex:功能最全的弹性布局。
通过组合这些容器,我们可以构建出任何复杂的静态页面。尝试修改布局属性,观察UI的变化,可以加深对布局系统的理解。