前言

在鸿蒙 ArkTS 的声明式 UI 开发中,无论界面多么复杂,其底层结构往往都是由最基础的线性布局和层叠布局搭建而成的。Column(垂直布局)、Row(水平布局)和 Stack(层叠布局)被开发者们亲切地称为“UI布局三剑客”。掌握这三者的用法,就相当于拿到了构建任意复杂界面的钥匙。

一、线性布局:Column 与 Row

线性布局是最基础也最常用的布局方式,它的核心逻辑是让子组件按照单一方向依次排列。

1. Column:垂直方向的“排队高手”
Column 容器会让其内部的子元素在垂直方向上从上到下依次排列。它非常适合用来构建列表、表单或者页面的整体纵向结构。

  • 主轴与交叉轴:在 Column 中,主轴是垂直方向,交叉轴是水平方向。
  • 核心属性
    • space:设置子元素在主轴(垂直)方向上的间距。
    • alignItems:控制子元素在交叉轴(水平)方向的对齐方式(如居左 Start、居中 Center、居右 End)。
    • justifyContent:控制子元素在主轴(垂直)方向上的整体分布(如顶部 Start、居中 Center、底部 End、均匀分布等)。

2. Row:水平方向的“并排搭档”
Row 容器则让子元素在水平方向上从左到右依次排列。它是构建导航栏、工具栏、按钮组以及表单中“标签+输入框”组合的利器。

  • 主轴与交叉轴:在 Row 中,主轴是水平方向,交叉轴是垂直方向。
  • 核心属性
    • space:设置子元素在主轴(水平)方向上的间距。
    • alignItems:控制子元素在交叉轴(垂直)方向的对齐方式(如顶部 Top、居中 Center、底部 Bottom)。
    • justifyContent:控制子元素在主轴(水平)方向上的整体分布。

代码实战:线性布局基础

@Entry
@Component
struct LinearLayoutExample {
  build() {
    // 外层使用 Column 垂直排列两个区域
    Column({ space: 20 }) { 
      Text('Row 水平布局示例').fontSize(18).fontWeight(FontWeight.Bold)
      
      // Row 水平排列三个按钮,间距为 10,整体在交叉轴(垂直)居中
      Row({ space: 10 }) {
        Button('左').backgroundColor(Color.Blue)
        Button('中').backgroundColor(Color.Green)
        Button('右').backgroundColor(Color.Orange)
      }
      .width('100%')
      .height(60)
      .backgroundColor('#f0f0f0')
      .alignItems(VerticalAlign.Center) // 交叉轴对齐:垂直居中
      .justifyContent(FlexAlign.Center) // 主轴对齐:水平居中

      Text('Column 垂直布局示例').fontSize(18).fontWeight(FontWeight.Bold)

      // Column 垂直排列三个文本,间距为 15,整体在交叉轴(水平)居左
      Column({ space: 15 }) {
        Text('第一行内容').fontSize(16).width('80%').height(40).backgroundColor(Color.Pink)
        Text('第二行内容').fontSize(16).width('60%').height(40).backgroundColor(Color.Yellow)
        Text('第三行内容').fontSize(16).width('90%').height(40).backgroundColor('#00FFFF')
      }
      .width('100%')
      .alignItems(HorizontalAlign.Start) // 交叉轴对齐:水平居左
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }
}
二、层叠布局:Stack

如果说线性布局是“排队”,那么 Stack 就是“叠罗汉”。Stack 容器允许子组件在屏幕上同一块区域内进行重叠显示。容器内的子元素会依次入栈,后一个子元素会覆盖在前一个子元素的上方。

Stack 具有极强的位置定位能力,常用于实现带有角标的图标、卡片层叠效果、广告弹窗或者复杂的图文叠加界面。

  • 核心属性
    • alignContent:控制容器内所有子元素的整体对齐方式(支持九宫格定位,如 TopStart 左上、Center 居中、BottomEnd 右下等)。
    • zIndex:控制子元素的显示层级,值越大,显示层级越高(越靠上)。

代码实战:层叠布局基础


@Entry
@Component
struct StackLayoutExample {
  build() {
    Column() {
      Text('Stack 层叠布局示例').fontSize(18).fontWeight(FontWeight.Bold).margin({ bottom: 20 })

      // 新增一个外层容器(如 Row),专门用来控制 Stack 的整体位置
      Row() {
        // Stack 容器,整体内容在右下角对齐
        Stack({ alignContent: Alignment.BottomEnd }) {
          // 底层:一个大的背景方块
          Column()
            .width(200)
            .height(200)
            .backgroundColor(Color.Blue)

          // 中间层:一个中等大小的方块
          Column()
            .width(140)
            .height(140)
            .backgroundColor(Color.Green)

          // 顶层:一个小的红色角标
          Text('New')
            .width(50)
            .height(50)
            .fontSize(14)
            .fontColor(Color.White)
            .backgroundColor(Color.Red)
            .textAlign(TextAlign.Center)
            .borderRadius(25) // 圆形角标
        }
        .width('100%')
        .height(250)
        .backgroundColor('#f5f5f5')
        // Stack 内部的对齐方式通过 alignContent 参数控制,比如 Alignment.BottomEnd
      }
      .width('100%')
      .justifyContent(FlexAlign.Center) // 让 Stack 整体在 Row 中水平居中展示
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }
}
三、布局嵌套与实战技巧

在实际开发中,我们往往需要将这三种布局容器进行相互嵌套,才能构建出丰富多彩的复杂页面。

核心口诀

  • 想上下排,用 Column
  • 想左右排,用 Row
  • 想盖在一起,用 Stack

例如,一个常见的“带未读消息角标的底部导航栏”,就可以通过 Row(水平排列导航项)嵌套 Stack(在每个导航项上叠放角标)来实现。建议你在 DevEco Studio 的预览器中多尝试修改 spacealignItems 和 justifyContent 等属性,直观感受它们对布局的影响。

四、进阶补充:Flex 弹性布局

在实际开发中,如果子组件数量不固定,或者希望一行放不下时自动换行,Row 和 Column 就显得力不从心了。这时就需要请出它们的“老大哥”—— Flex 容器

Flex 可以看作是 Row 和 Column 的超集,它不仅能控制主轴方向,还支持换行机制

核心属性:

  • direction:设置主轴方向(Row, Column, RowReverse, ColumnReverse)。
  • wrap:控制是否换行(NoWrap 不换行,Wrap 正常换行,WrapReverse 反向换行)。这在实现“标签云”或“九宫格图片列表”时非常有用。
  • justifyContent / alignItems:与 Row/Column 用法一致,但配合 wrap 属性可以实现更复杂的网格对齐效果。

代码实战:标签云效果

@Entry
@Component
struct FlexLayoutExample {
  build() {
    Column({ space: 10 }) {
      Text('Flex 弹性换行示例').fontSize(18).fontWeight(FontWeight.Bold)

      // 创建一个横向排列、允许换行的 Flex 容器
      Flex({ direction: FlexDirection.Row, wrap: FlexWrap.Wrap, justifyContent: FlexAlign.Start }) {
        ForEach(['鸿蒙', 'ArkTS', '声明式UI', 'DevEco Studio', '性能优化', '分布式'], (tag: string) => {
          Text(tag)
            .fontSize(14)
            .padding({ left: 12, right: 12, top: 6, bottom: 6 })
            .backgroundColor('#E3F2FD')
            .fontColor('#1976D2')
            .borderRadius(15)
            .margin({ right: 8, bottom: 8 }) // 注意:这里用 margin 控制间距比用 space 更安全
        })
      }
      .width('100%')
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }
}


五、避坑指南:布局嵌套的“黄金法则”

掌握了基础布局后,新手最容易犯的错误就是过度嵌套。在 ArkTS 的渲染引擎中,每一个布局容器都会带来额外的计算开销。为了保证应用的丝滑流畅,请务必牢记以下原则:

  1. 能用单层解决的,绝不套两层:例如,想实现“水平居中且垂直靠底”的效果,不需要外面套一个 Column 再里面套一个 Row,直接使用 RelativeContainer 或 Flex 即可一步到位。
  2. 优先使用 RelativeContainer:官方强烈推荐使用相对布局来替代深层级的 Row/Column 嵌套。RelativeContainer 通过锚点定位,可以将原本需要三四层嵌套的界面扁平化为一层,大幅降低渲染耗时。
  3. 避免在列表项中使用复杂嵌套:在 List 或 LazyForEach 的 itemBuilder 内部,尽量保持结构扁平。如果一个列表项里嵌套了四五层布局,滑动时极易出现掉帧卡顿。

总结:Column、Row、Stack 是地基,Flex 是扩展工具,而合理的架构思维则是摩天大楼不倒的保障。建议在 DevEco Studio 中多画几层不同的布局组合,直观感受它们对性能和界面的影响。

更多推荐