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)

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

3. 绘制阶段(Draw Pass)

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

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


二、线性布局:Column 与 Row

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

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 跨列与跨行

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


六、响应式与自适应布局

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

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

相关推荐
程序员黑豆18 小时前
鸿蒙应用开发:@Computed 装饰器详解与实战
前端·harmonyos
ldsweet18 小时前
HarmonyOS NEXT 音频播放器开发:AVPlayer 封装、播放列表与后台播放实战
华为·音视频·harmonyos
qizayaoshuap18 小时前
# 44号应用:标签管理 — Flex 流式标签与交互状态设计
华为·harmonyos
哎呦喂我去去去20 小时前
HarmonyOS SDK助力讯飞听见App能力建设
华为·harmonyos
lilian2331 天前
# Harmony os 技术实战|拼豆制图05:让 50 张本地图纸搜得准、排得稳
华为·harmonyos
想你依然心痛1 天前
Slider 滑块组件深度解析与交互定制全攻略
harmonyos·arkui·slider·双向绑定·sliderchange·sliderange·contentmodifier
2501_919749031 天前
华为鸿蒙类似小蓝书APP—小羊书
华为·harmonyos
独守一片天1 天前
HarmonyOS 安全隐私权限治理从最小权限到上架审核的一套工程规范
安全·华为·harmonyos
程序员黑豆2 天前
鸿蒙应用开发:@Monitor 装饰器使用教程
前端·harmonyos