ArkTS 布局系统概述——从线性到网格,掌握声明式 UI 的骨架艺术

文章目录

      • 每日一句正能量
      • 引言
      • [一、ArkUI 布局系统架构:理解渲染管线](#一、ArkUI 布局系统架构:理解渲染管线)
      • [二、线性布局:Column 与 Row](#二、线性布局:Column 与 Row)
        • [2.1 核心属性](#2.1 核心属性)
        • [2.2 代码示例:设置列表项](#2.2 代码示例:设置列表项)
        • [2.3 自适应拉伸:layoutWeight 与 Blank](#2.3 自适应拉伸:layoutWeight 与 Blank)
      • 三、弹性布局:Flex
        • [3.1 核心参数](#3.1 核心参数)
        • [3.2 子组件弹性属性](#3.2 子组件弹性属性)
        • [3.3 Flex 与 Column/Row 的选型策略](#3.3 Flex 与 Column/Row 的选型策略)
      • 四、层叠布局:Stack
        • [4.1 定位方式](#4.1 定位方式)
        • [4.2 典型应用场景](#4.2 典型应用场景)
      • 五、网格布局:Grid
        • [5.1 基础用法](#5.1 基础用法)
        • [5.2 跨列与跨行](#5.2 跨列与跨行)
      • 六、响应式与自适应布局
        • [6.1 栅格断点规则](#6.1 栅格断点规则)
        • [6.2 GridContainer 与 useSizeType](#6.2 GridContainer 与 useSizeType)
      • 七、布局性能优化实践
      • 八、总结

每日一句正能量

"不经思考的行动,到头来只会是无用功。"

没有经过倾听、观察、思考的匆忙行动,往往偏离目标或重复错误。行动之前要先"听见"事实与反馈,否则再努力也是徒劳。

向内建立清晰的边界与自省,再向外选择对的人与事,以倾听和包容为方法,最终达到不费力却深刻的默契与从容。


引言

在 HarmonyOS 应用开发中,UI 界面不仅是视觉的呈现,更是用户与系统交互的桥梁。ArkTS 作为 HarmonyOS 主推的声明式开发语言,其布局系统经历了从传统命令式到现代声明式的范式革命。与早期需要开发者手动计算坐标、逐像素调整位置的命令式布局不同,ArkTS 的布局系统通过组合式 API 让开发者以更接近自然语义的方式描述界面结构,框架自动完成测量、布局与绘制。

本文将系统梳理 ArkTS 布局体系的核心容器与机制,涵盖线性布局、弹性布局、层叠布局、网格布局及响应式适配方案,并结合实际代码示例与性能优化策略,帮助开发者建立完整的布局思维模型。


一、ArkUI 布局系统架构:理解渲染管线

在深入具体布局容器之前,有必要先理解 ArkUI 布局引擎的工作流程。一个组件最终能显示在屏幕的哪个位置,通常会经历三个阶段:

1. 测量阶段(Measure Pass)

父组件向子组件传递可用空间和尺寸约束,子组件根据内容、显式尺寸与约束计算自身大小。例如,当父容器宽度为 400vp,子组件设置了 width('50%'),则其实际测量宽度为 200vp。

2. 布局阶段(Layout Pass)

父组件按照自身的布局规则,结合子组件的测量结果,确定每个子组件在容器内的最终坐标位置。这一阶段决定了组件的 x、y 偏移量。

3. 绘制阶段(Draw Pass)

将布局结果渲染到屏幕,生成具体的渲染指令,处理背景、边框、阴影和内容绘制。

ArkUI 3.0 之后引入了增量布局机制,仅重新计算发生变更的部分,而非整棵树重排。同时支持 AsyncMeasure 异步测量,优化复杂嵌套场景下的布局性能。声明式语法使得开发者只需描述 UI 应该「长什么样」,而无需关心「怎么画」,框架内部通过 Diff 算法直接基于 RENDER 树节点比较差异,实现渲染算法树三合一,界面滑动加载速度较传统方案提升约 45%。


二、线性布局:Column 与 Row

线性布局是 ArkTS 中最基础、最常用的布局方式,通过 Column 和 Row 两个容器组件实现。

Column 容器内子组件按照垂直方向依次排列,适用于纵向堆叠的场景,如表单、设置列表、卡片内容等。

Row 容器内子组件按照水平方向依次排列,适用于横向排列的场景,如导航栏、工具栏、标签组等。

2.1 核心属性
属性 作用 Column 取值 Row 取值
space 主轴方向子组件间距 数值 数值
justifyContent 主轴对齐方式 FlexAlign FlexAlign
alignItems 交叉轴对齐方式 HorizontalAlign VerticalAlign
2.2 代码示例:设置列表项
typescript 复制代码
@Entry
@Component
struct SettingsPage {
  build() {
    Column({ space: 12 }) {
      // 标题栏
      Row() {
        Text('设置').fontSize(24).fontWeight(FontWeight.Bold)
        Blank() // 自动填充空白
        Image($r('app.media.close')).width(24).height(24)
      }
      .width('100%')
      .padding(16)

      // 设置项列表
      Column({ space: 8 }) {
        this.buildSettingItem('Wi-Fi', true)
        this.buildSettingItem('蓝牙', false)
        this.buildSettingItem('通知', true)
        this.buildSettingItem('定位服务', false)
      }
      .width('100%')
      .padding({ left: 16, right: 16 })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F7FA')
  }

  @Builder
  buildSettingItem(label: string, isOn: boolean) {
    Row() {
      Text(label).fontSize(16).fontColor('#333333')
      Blank()
      Toggle({ type: ToggleType.Switch, isOn: isOn })
    }
    .width('100%')
    .height(56)
    .padding({ left: 16, right: 16 })
    .backgroundColor(Color.White)
    .borderRadius(12)
  }
}
2.3 自适应拉伸:layoutWeight 与 Blank

在线性布局中,layoutWeight 属性用于配置子组件在主轴方向上的尺寸权重。配置该属性后,子组件沿主轴方向的显式尺寸设置将失效,具体尺寸根据权重比例自动计算。Blank 组件则是一个空白填充组件,在容器主轴方向自动填充剩余空间,常用于实现左右对齐的列表项布局。


三、弹性布局:Flex

弹性布局(Flex)的效果类似于线性布局,同样使子元素呈线性排列,但在子元素的排列、对齐和剩余空间分配等方面更加灵活。Flex 是 Web 开发者最熟悉的布局模型之一,ArkTS 完整复刻了 CSS Flexbox 的核心能力。

3.1 核心参数
参数 类型 说明
direction FlexDirection 主轴方向:Row / Column / RowReverse / ColumnReverse
wrap FlexWrap 换行方式:NoWrap / Wrap / WrapReverse
justifyContent FlexAlign 主轴对齐
alignItems ItemAlign 交叉轴对齐
alignContent FlexAlign 多行内容对齐(wrap 生效时)
3.2 子组件弹性属性
typescript 复制代码
Flex({ direction: FlexDirection.Row, wrap: FlexWrap.Wrap }) {
  Text('标签 A')
    .width(80)
    .height(40)
    .backgroundColor('#FF9F43')
    .flexGrow(1)  // 空间充足时按比例扩展

  Text('标签 B')
    .width(80)
    .height(40)
    .backgroundColor('#10AC84')
    .flexGrow(2)  // 分得更多剩余空间

  Text('标签 C')
    .width(80)
    .height(40)
    .backgroundColor('#5F27CD')
    .flexShrink(0) // 空间不足时不压缩
}
.width('100%')
.padding(12)
3.3 Flex 与 Column/Row 的选型策略

Column/Row 适用于:简单线性排列、页面骨架结构、固定数量的子项、追求代码简洁和极致性能的场景。由于不支持换行,布局计算路径更短,渲染性能更优。

Flex 适用于:需要自动换行(wrap)、多行对齐(alignContent)、主轴方向动态切换、子项数量和大小不确定的流式内容场景。最佳实践是外层用 Column/Row 搭骨架,内层动态区域用 Flex 处理流式内容,两者分层协作。


四、层叠布局:Stack

层叠布局(Stack)用于在屏幕上预留一块区域来显示组件中的元素,提供元素可以重叠的布局能力。容器中的子元素依次入栈,后一个子元素覆盖前一个子元素,类似于 Photoshop 中的图层叠加。

4.1 定位方式

Stack 容器支持两种定位方式:

  • 默认定位:子组件按添加顺序依次叠加,无偏移时中心对齐
  • 绝对定位 :通过 position({ x, y }) 或 offset({ x, y }) 精确控制位置
4.2 典型应用场景
typescript 复制代码
@Entry
@Component
struct StackDemo {
  build() {
    Stack({ alignContent: Alignment.Center }) {
      // 底层:背景图
      Image($r('app.media.cover'))
        .width('100%')
        .height(200)
        .objectFit(ImageFit.Cover)

      // 中层:半透明遮罩
      Column()
        .width('100%')
        .height(200)
        .backgroundColor('rgba(0,0,0,0.4)')

      // 顶层:文字内容
      Column() {
        Text('鸿蒙生态赋能')
          .fontSize(24)
          .fontColor(Color.White)
          .fontWeight(FontWeight.Bold)
        Text('第五期技术实战')
          .fontSize(14)
          .fontColor('#DDDDDD')
          .margin({ top: 8 })
      }
    }
    .width('100%')
    .height(200)
  }
}

层叠布局的典型应用场景包括:广告弹窗、卡片层叠效果、图片水印叠加、视频播放控制层叠加等。通过 zIndex 属性还可以手动控制层级顺序,数值越大越靠上。


五、网格布局:Grid

网格布局(Grid)是一种二维布局系统,支持将容器划分为若干行和列,子组件按照指定的行列位置进行放置。相比线性布局的一维排列,网格布局能更高效地实现复杂的卡片矩阵、相册网格、仪表盘等界面。

5.1 基础用法
typescript 复制代码
@Entry
@Component
struct GridDemo {
  private items: string[] = ['相册', '相机', '日历', '时钟', '天气', '地图']

  build() {
    Grid() {
      ForEach(this.items, (item: string, index: number) => {
        GridItem() {
          Column() {
            Image($r(`app.media.icon_${index}`))
              .width(48)
              .height(48)
            Text(item)
              .fontSize(14)
              .margin({ top: 8 })
          }
          .width('100%')
          .height('100%')
          .justifyContent(FlexAlign.Center)
        }
        .backgroundColor('#F5F7FA')
        .borderRadius(16)
      })
    }
    .columnsTemplate('1fr 1fr 1fr')  // 三列等宽
    .rowsTemplate('1fr 1fr')         // 两行等高
    .columnsGap(12)
    .rowsGap(12)
    .padding(16)
    .width('100%')
    .height(400)
  }
}
5.2 跨列与跨行

通过 columnStart、columnEnd、rowStart、rowEnd 属性,子组件可以跨越多个网格单元格,实现类似「大图+小图」的复杂布局效果。


六、响应式与自适应布局

HarmonyOS 应用需要同时适配手机、平板、折叠屏、2in1 设备等多种形态,响应式布局是不可或缺的能力。ArkTS 提供了基于断点的栅格系统,以设备水平宽度(vp)作为断点依据。

6.1 栅格断点规则
设备宽度 类型 列数 间隔 边距
0 ~ 320vp XS 2 12vp 12vp
320 ~ 600vp SM 4 24vp 24vp
600 ~ 840vp MD 8 24vp 32vp
≥ 840vp LG 12 24vp 48vp
6.2 GridContainer 与 useSizeType
typescript 复制代码
GridContainer() {
  Row() {
    Text('自适应卡片')
      .useSizeType({
        xs: { span: 2, offset: 0 },   // 手机:占满2列
        sm: { span: 2, offset: 0 },   // 大屏手机:占2列
        md: { span: 4, offset: 0 },   // 平板:占4列
        lg: { span: 6, offset: 0 },   // 2in1:占6列
      })
  }
}

通过 useSizeType 属性,开发者可以为同一组件在不同断点下指定不同的列跨度(span)和偏移量(offset),实现真正的「一次开发,多端部署」。


七、布局性能优化实践

布局性能直接影响应用的流畅度和用户体验。以下是 ArkTS 布局优化的核心策略:

1. 减少布局层级嵌套

每增加一层嵌套,就会多一轮 Measure 和 Layout 计算。尽量扁平化组件树,能用单层 Flex 解决的不用嵌套 Column+Row。

2. 优先使用 Column/Row 而非 Flex

Column/Row 只处理一维线性排列,布局计算路径更短,渲染性能优于 Flex。仅在需要换行、多行对齐等 Flex 特有能力时才使用 Flex。

3. 避免在循环中创建复杂布局

对于长列表,使用 LazyForEach 替代 ForEach,配合 cachedCount 预加载缓存项,避免一次性渲染全部子组件。

4. 合理使用固定尺寸

当组件内容尺寸确定时,优先使用固定数值(如 width(200))而非百分比或自适应计算,可减少测量阶段的递归开销。

5. 利用 freezeWhenInactive 冻结不可见组件

对于不可见或离屏组件,启用 freezeWhenInactive 减少不必要的布局刷新和重绘。

typescript 复制代码
List() {
  LazyForEach(this.dataSource, (item: Item) => {
    ListItem() {
      ItemComponent({ item: item })
    }
    .freezeWhenInactive(true)
  })
}
.cachedCount(3)  // 预加载3个缓存项

八、总结

ArkTS 的布局系统以声明式语法为核心,通过 Column/Row、Flex、Stack、Grid 等丰富的容器组件,覆盖了从简单线性排列到复杂二维网格的全场景需求。理解各容器的设计哲学与能力边界,是写出高效、优雅、可维护 UI 代码的前提。

在实际开发中,建议遵循以下原则:

  • 骨架层用 Column/Row:页面整体结构采用线性布局搭建,保证性能与可读性
  • 动态区用 Flex:标签流、按钮组等动态内容区域使用 Flex 的换行与弹性能力
  • 叠加区用 Stack:弹窗、遮罩、水印等层叠场景使用 Stack 实现
  • 矩阵区用 Grid:卡片矩阵、相册、仪表盘等二维排列使用 Grid 实现
  • 跨端用 GridContainer:响应式场景下结合断点与栅格系统实现多端自适应

掌握这套布局体系,你就掌握了 ArkTS 声明式 UI 的骨架艺术,为构建高性能、高颜值的 HarmonyOS 应用打下坚实基础。


转载自:https://blog.csdn.net/u014727709/article/details/163198448

欢迎 👍点赞✍评论⭐收藏,欢迎指正

相关推荐
李游Leo4 小时前
《HarmonyOS 7 ArkGraphics 3D 空间设计开发实战》03:glTF模型加载、实例复用与资源生命周期【鸿蒙心迹】
3d·harmonyos
李游Leo5 小时前
HarmonyOS 7 + ArkTS-HUKS:精准碰一碰载荷的签名校验与重放窗口【鸿蒙心迹】
华为·harmonyos
花花_15 小时前
HarmonyOS 7 状态手记 01|页面状态别乱放
华为·harmonyos
李游Leo6 小时前
HarmonyOS 7 + Hvigor-Localization Kit:多语言资源占位符签名与回退链路预检【鸿蒙心迹】
harmonyos
李游Leo6 小时前
HarmonyOS 7 AVSession + Float Window:闪控窗播放控制权的会话移交与重复指令去重【鸿蒙心迹】
华为·harmonyos
李游Leo6 小时前
HarmonyOS 7 + ArkTS-UDMF:精准碰一碰载荷的协议版本协商与字段降级【鸿蒙心迹】
华为·harmonyos
李游Leo7 小时前
HarmonyOS 7 + Core Vision Kit-TaskPool:文搜图相似度阈值分桶与硬负样本回流【鸿蒙心迹】
华为·harmonyos
李游Leo8 小时前
HarmonyOS 7 EasyGo + ArkUI Navigation:平行视界导航模式的列表选中态、右栏路由栈与全局返回收口【鸿蒙心迹】
华为·harmonyos
李游Leo8 小时前
HarmonyOS 7 + ArkUI Accessibility:闪控窗紧凑态的语义树裁剪与读屏焦点收敛【鸿蒙心迹】
华为·harmonyos
李游Leo9 小时前
HarmonyOS 7 ArkUI Navigation + WindowStage:折叠屏窗口宽度驱动的单双栏切换与草稿状态保持【鸿蒙心迹】
华为·harmonyos