HarmonyOS鸿蒙Next中Column、Row、Stack、Flex、Grid、List等布局容器如何选择和使用?

HarmonyOS鸿蒙Next中Column、Row、Stack、Flex、Grid、List等布局容器如何选择和使用? 我在开发 HarmonyOS 应用 UI 时,对布局容器的选择比较困惑,想了解:

  1. Column(垂直)和 Row(水平)布局如何设置 space、alignItems、justifyContent?

  2. Stack 层叠布局的使用场景是什么?如何控制子元素的层级?

  3. Flex 弹性布局与 Row/Column 有什么区别?wrap 换行如何实现?

  4. Grid 网格布局如何定义行列模板?

  5. List 列表布局如何实现滚动和懒加载?

希望能获取各布局容器的对比说明和代码示例。


更多关于HarmonyOS鸿蒙Next中Column、Row、Stack、Flex、Grid、List等布局容器如何选择和使用?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

查看官方文档和HMOS代码工坊

更多关于HarmonyOS鸿蒙Next中Column、Row、Stack、Flex、Grid、List等布局容器如何选择和使用?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


实现思路:

  1. 使用 Column 垂直布局和 Row 水平布局,通过 space 设置间距,alignItems 设置对齐方式:
Column({ space: 12 }) {
  Text('标题')
  Text('内容')
}
.alignItems(HorizontalAlign.Start)

Row({ space: 8 }) {
  Image($r('app.media.icon')).width(40)
  Text('文字')
  Blank()  // 占据剩余空间
  Text('>')
}
.alignItems(VerticalAlign.Center)
  1. 使用 Stack 层叠布局实现悬浮效果,后面的组件覆盖前面的:
Stack({ alignContent: Alignment.BottomEnd }) {
  Image($r('app.media.photo')).width('100%').height(200)
  // 角标覆盖在图片上
  Text('NEW')
    .fontSize(10)
    .fontColor(Color.White)
    .backgroundColor(Color.Red)
    .padding(4)
    .margin(8)
}
  1. 使用 Flex 弹性布局实现自动换行:
Flex({ wrap: FlexWrap.Wrap }) {
  ForEach(this.tags, (tag: string) => {
    Text(tag)
      .padding({ left: 12, right: 12, top: 6, bottom: 6 })
      .backgroundColor('#F0F0F0')
      .borderRadius(16)
      .margin(4)
  })
}
  1. 完整示例代码:
@Entry
@Component
struct LayoutExample {
  @State tags: string[] = ['标签1', '标签2', '标签3', '标签4', '标签5'];
  @State gridItems: string[] = ['1', '2', '3', '4', '5', '6'];
  @State listItems: string[] = ['列表项1', '列表项2', '列表项3', '列表项4', '列表项5'];

  build() {
    Column({ space: 16 }) {
      // Row 水平布局
      Row({ space: 8 }) {
        Image($r('app.media.icon')).width(48).height(48)
        Column() {
          Text('标题').fontSize(16).fontWeight(FontWeight.Bold)
          Text('副标题').fontSize(12).fontColor('#666')
        }
        .alignItems(HorizontalAlign.Start)
        Blank()
        Text('详情 >').fontColor('#999')
      }
      .width('100%')
      .padding(12)
      .backgroundColor('#FFF')
      .borderRadius(8)

      // Stack 层叠布局
      Stack({ alignContent: Alignment.BottomEnd }) {
        Image($r('app.media.photo')).width('100%').height(120).borderRadius(8)
        Text('HOT')
          .fontSize(10)
          .fontColor(Color.White)
          .backgroundColor('#FF6600')
          .padding(4)
          .borderRadius(4)
          .margin(8)
      }

      // Flex 弹性布局(自动换行)
      Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.Start }) {
        ForEach(this.tags, (tag: string) => {
          Text(tag)
            .fontSize(12)
            .padding({ left: 12, right: 12, top: 6, bottom: 6 })
            .backgroundColor('#F0F0F0')
            .borderRadius(16)
            .margin(4)
        })
      }

      // Grid 网格布局
      Grid() {
        ForEach(this.gridItems, (item: string) => {
          GridItem() {
            Column() {
              Text(item).fontSize(24)
            }
            .width('100%')
            .height(60)
            .justifyContent(FlexAlign.Center)
            .backgroundColor('#F5F5F5')
            .borderRadius(8)
          }
        })
      }
      .columnsTemplate('1fr 1fr 1fr')  // 3列等宽
      .rowsGap(8)
      .columnsGap(8)
      .height(140)

      // List 列表布局
      List({ space: 8 }) {
        ForEach(this.listItems, (item: string) => {
          ListItem() {
            Text(item)
              .width('100%')
              .padding(16)
              .backgroundColor('#FFF')
              .borderRadius(8)
          }
        })
      }
      .width('100%')
      .height(200)
      .scrollBar(BarState.Auto)
    }
    .width('100%')
    .height('100%')
    .padding(16)
    .backgroundColor('#F5F5F5')
  }
}

在HarmonyOS鸿蒙Next中,布局容器选择依据如下:

  • Column:垂直排列子组件。
  • Row:水平排列子组件。
  • Stack:子组件重叠堆叠(如层叠视图)。
  • Flex:弹性布局,通过FlexDirection设置主轴方向(行或列)。
  • Grid:网格布局,用于规整行列排列。
  • List:列表布局,支持滚动和大量数据展示。

使用方式:在ArkUI中声明容器组件并添加子组件,通过属性调整对齐、间距等。

针对你的问题,这里对各布局容器进行简要对比和核心使用说明。

1. Column 与 Row 这是最基础的线性布局容器,分别沿垂直和水平方向排列子组件。

  • space: 使用 space({ type: SpaceType.Between / Around / Evenly })justifyContent(FlexAlign.SpaceBetween / SpaceAround / SpaceEvenly) 设置子组件间的间距。
  • alignItems: 设置子组件在交叉轴上的对齐方式(Column的交叉轴是水平,Row的交叉轴是垂直)。例如 Column({ space: 10 }) { ... }.alignItems(HorizontalAlign.Center)
  • justifyContent: 设置子组件在主轴上的对齐方式(Column的主轴是垂直,Row的主轴是水平)。例如 Row() { ... }.justifyContent(FlexAlign.Center)

2. Stack 用于子组件的层叠摆放,典型场景如:文字叠加在图片上、浮动按钮、模态弹窗。

  • 控制层级: 默认后声明的子组件层级更高(覆盖在先声明的组件之上)。可以使用 .zIndex() 属性手动控制,数值大的在上层。

3. Flex 弹性布局 Flex 是 Row/Column 的父集,功能更强大。

  • 与 Row/Column 的区别: Row/Column 是主轴方向固定的 Flex。Flex 可以通过 direction: FlexDirection.Row / Column 动态设置主轴方向,更灵活。
  • wrap 换行: 直接设置 .wrap(FlexWrap.Wrap) 即可实现主轴空间不足时换行,配合 justifyContentalignItemsalignContent 控制多行对齐。

4. Grid 网格布局 用于规整的二维网格布局。

  • 定义行列模板: 通过 columnsTemplaterowsTemplate 定义。支持固定值(如 '100px')、比例(如 '1fr 2fr')、重复(如 'repeat(3, 1fr)')和自适应('auto')。
    Grid() { ... }
    .columnsTemplate('1fr 2fr 1fr')
    .rowsTemplate('100px auto 100px')
    

5. List 列表布局 用于长列表数据展示,核心特性是滚动和性能优化。

  • 实现滚动: List 默认支持垂直滚动,无需额外设置。
  • 懒加载: List 内置了按需渲染(懒加载)机制。关键在于为 List 提供数据源(如 @State 数组),并在子组件生成函数中使用 ForEachLazyForEach 来迭代渲染。LazyForEach 在数据量极大时性能更优,它只会创建可视区域及附近的列表项。

选择建议

  • 线性单行/列布局: 首选 RowColumn,简单直观。
  • 层叠: 必须使用 Stack
  • 需要换行或动态方向: 使用 Flex
  • 规整的二维矩阵: 使用 Grid
  • 可滚动的长列表: 必须使用 List,并配合 ForEach/LazyForEach
回到顶部