欢迎光临
我们一直在努力

【共创季稿事节】鸿蒙原生 ArkTS 布局实战:Column 主轴三种分布模式(SpaceBetween / SpaceAround / SpaceEvenly)深度解析

【共创季稿事节】鸿蒙原生 ArkTS 布局实战:Column 主轴三种分布模式(SpaceBetween / SpaceAround / SpaceEvenly)深度解析

本文参与「鸿蒙原生 ArkTS 布局实战」征文活动
开发环境:HarmonyOS NEXT (API 23+) | DevEco Studio 5.0+
项目源码:GitHub — harmonyOSZhengWen


在这里插入图片描述
首页展示

一、写在前面

1.1 鸿蒙生态新篇章

2025 年,HarmonyOS NEXT 正式迈入独立生态的新纪元。这个去掉了 Android 兼容层、完全拥抱鸿蒙内核的操作系统,带来了全新的开发范式和用户体验。对于开发者而言,这意味着真正的「纯血鸿蒙」时代已经到来——不再有 Java 和 Kotlin 的遗留包袱,不再有跨平台桥接的性能损耗,一切从零开始,用鸿蒙原生的方式构建应用。

而在鸿蒙原生应用开发中,ArkUI 声明式 UI 框架是最核心的技术栈。它采用类似 SwiftUI 和 Flutter 的声明式语法,通过 TypeScript 的超集 ArkTS 语言来描述界面,让 UI 代码更简洁、更可预测。

1.2 布局 —— 鸿蒙开发的基石

每个开发者接触一个新 UI 框架时,首先要面对的都是布局问题。布局是构建用户界面的第一道门槛:你需要在屏幕上精确放置每一个元素,控制它们之间的间距、对齐方式和排列顺序。

在 ArkUI 中,布局主要依赖以下几个核心容器:

容器主轴方向对应 Web Flexbox典型应用
Column 垂直(纵向) flex-direction: column 列表、表单、页面骨架
Row 水平(横向) flex-direction: row 导航栏、按钮组、标签栏
Flex 可自定义 display: flex 复杂弹性布局
Stack 层叠 position: absolute 叠加层、悬浮按钮

在这些容器中,Column 是最常用、最基础的一个。从简单的文字排列到复杂的页面骨架,Column 几乎无处不在。而 Column 的 justifyContent 属性,则是控制子组件在垂直方向上分布方式的关键。

1.3 三个让人困惑的 FlexAlign 值

很多刚刚接触 ArkUI 的开发者,在看到 FlexAlign.SpaceBetween、FlexAlign.SpaceAround 和 FlexAlign.SpaceEvenly 这三个枚举值时,常常一头雾水:

  • “SpaceBetween 和 SpaceAround 有什么区别?”
  • “SpaceEvenly 和 SpaceAround 不是一样的吗?”
  • “我该在什么时候用哪一个?”

这三个模式看起来相似,但实际上在间距计算上有本质区别。如果选错了,布局效果会完全不同——该贴边的没贴边,该留白的没留白。

为了彻底帮大家搞清楚这个问题,我编写了一个完整的 HarmonyOS NEXT 交互式演示应用,用可视化的方式展示每种模式的真实行为。本文将从源码层面深度解析这个应用,逐行讲解关键实现,并分享实战中的最佳实践和常见坑点。


二、项目全景

2.1 应用介绍

「Column 布局方式演示」是一个纯鸿蒙原生的交互式教育应用,它通过三个独立的演示页面,分别展示 SpaceBetween、SpaceAround 和 SpaceEvenly 三种主轴分布模式的行为特征。

2.2 项目结构

harmonyOSZhengWen/
├── AppScope/
│ └── app.json5 # 应用全局配置
├── entry/
│ ├── src/main/ets/
│ │ ├── entryability/
│ │ │ └── EntryAbility.ets # 应用入口 Ability
│ │ ├── entrybackupability/
│ │ │ └── EntryBackupAbility.ets # 备份恢复能力
│ │ └── pages/
│ │ ├── Index.ets # 导航首页
│ │ ├── ColumnSpaceBetween.ets # SpaceBetween 布局演示
│ │ ├── ColumnSpaceAround.ets # SpaceAround 布局演示
│ │ └── ColumnSpaceEvenly.ets # SpaceEvenly 布局演示
│ ├── src/main/resources/
│ │ ├── base/element/
│ │ │ ├── color.json # 基础颜色资源
│ │ │ ├── float.json # 浮点数值资源
│ │ │ └── string.json # 字符串资源
│ │ ├── base/profile/
│ │ │ └── main_pages.json # 页面路由注册
│ │ └── dark/element/
│ │ └── color.json # 深色模式颜色覆盖
│ ├── src/main/module.json5 # 模块配置
│ ├── build-profile.json5 # 构建配置
│ └── oh-package.json5 # 包管理配置
├── hvigor/
│ └── hvigor-config.json5 # 构建工具配置
├── build-profile.json5 # 顶层构建配置
├── hvigorfile.ts # 构建脚本入口
├── oh-package.json5 # 顶层包管理
└── local.properties # 本地开发环境配置

2.3 技术栈

  • UI 框架:ArkUI(声明式 UI,HarmonyOS NEXT 原生)
  • 开发语言:ArkTS(TypeScript 的超集,强类型)
  • 最低 API 版本:API 23(HarmonyOS NEXT)
  • 页面路由:@kit.ArkUI 的 router 模块
  • 状态管理:@State 装饰器
  • 动画能力:.transition() + .animation() API
  • 第三方依赖:零依赖,全部为 ArkUI 内置 API

2.4 功能清单

功能模块说明
优雅导航首页 三张卡片式导航入口,渐变色装饰,点击跳转
SpaceBetween 演示 首尾贴边分布,2 个中间块可动态显隐
SpaceAround 演示 环绕分布,2 个中间块 + 高度模式切换
SpaceEvenly 演示 全等间距分布,3 个中间块 + 高度模式切换
动态控制按钮 点击显隐中间块,实时观察布局重排
平滑动画过渡 块出现/消失淡入淡出,布局变化过渡平滑
三种布局对比 每个页面底部都有完整的对比表格
返回导航 每个演示页面均可返回首页
深色模式兼容 通过资源限定词适配深色/亮色模式

三、ArkUI 布局体系深入理解

3.1 声明式 UI 的布局哲学

在深入分析具体代码之前,有必要先理解 ArkUI 声明式 UI 的布局哲学。与传统命令式 UI(如 Android View System、Qt Widgets)不同,声明式 UI 不再依赖开发者手动计算布局位置、调用 setX() / setY() 等方法,而是通过声明布局规则,让框架自行计算最终的渲染结果。

// 声明式 UI:你告诉框架「布局长什么样」
Column() {
Text('顶部')
Text('中部')
Text('底部')
}
.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
.height(300)

在上面这段代码中,你声明了一个纵向容器,里面有三个文本,主轴使用 SpaceBetween 分布。剩下的工作——计算每个文本的精确位置、间距大小——全部由 ArkUI 框架自动完成。这就是声明式 UI 的核心优势:关注「是什么」而不是「怎么做」。

3.2 主轴与交叉轴

在 ArkUI 中,每个 Flex 容器(Column、Row、Flex)都有两个轴:

  • 主轴(Main Axis):子组件排列的方向。Column 的主轴是垂直方向(从上到下),Row 的主轴是水平方向(从左到右)。
  • 交叉轴(Cross Axis):与主轴垂直的方向。Column 的交叉轴是水平方向,Row 的交叉轴是垂直方向。

justifyContent 控制的是主轴上的对齐方式,而 alignItems 控制的是交叉轴上的对齐方式。

←────── 交叉轴 ──────→
┌──────────────────────────┐
│ 子组件 A │ ↑
│ │ │ 主
│ 子组件 B │ │ 轴
│ │ │
│ 子组件 C │ ↓
└──────────────────────────┘

理解主轴和交叉轴的概念,是正确使用 flex 布局的基础。

3.3 FlexAlign 枚举全解析

ArkUI 的 FlexAlign 枚举定义了 6 种主轴对齐模式。其中前三种是基础对齐,后三种是空间分布模式:

基础对齐模式:

枚举值效果空间计算公式
Start 所有子组件从主轴起点开始排列 所有子组件在主轴起点端依次排列,剩余空间全部在终点端
Center 所有子组件在主轴居中排列 子组件整体居中,剩余空间平分到两端
End 所有子组件从主轴终点开始排列 所有子组件在主轴终点端依次排列,剩余空间全部在起点端

空间分布模式(本文重点):

枚举值效果空间计算公式
SpaceBetween 首尾贴边,中间均匀分布 有 n 个子组件 → n-1 个间隙,gap = (H – Σh) / (n-1)
SpaceAround 每项两侧环绕空间相等 有 n 个子组件 → n 个间隙单位,gap = (H – Σh) / n,两端各 gap/2
SpaceEvenly 所有空隙(含两端)完全相等 有 n 个子组件 → n+1 个间隙,gap = (H – Σh) / (n+1)

其中 H 为容器主轴方向的尺寸(Column 为高度),Σh 为所有子组件尺寸之和。

3.4 数学模型的直观理解

为了帮助记忆这三种分布模式,可以用一个简单的类比:

SpaceBetween 就像在两根固定柱子之间拉一根弹性绳:

  • 绳子两端绑在柱子上(首尾贴边)
  • 绳子上挂的物品均匀分布(中间均匀分布)
  • 柱子到第一个物品之间没有空隙(两端不留白)

SpaceAround 就像在一个包装盒里放物品,每个物品四周都有泡沫垫:

  • 第一个物品到盒子顶部的泡沫垫 = 中间泡沫垫厚度的一半
  • 每两个物品之间的泡沫垫厚度一致
  • 最后一个物品到盒子底部的泡沫垫 = 中间泡沫垫厚度的一半

SpaceEvenly 就像用切割机把盒子里的空间均匀切割:

  • 顶部空隙 = 物品间空隙 = 底部空隙
  • 一切都是等距的,数学上最完美

四、导航首页 —— 精美入口设计

4.1 设计目标

导航首页(Index.ets)的设计目标是:第一眼就让用户感受到精致和专业。作为应用的"门面",首页不仅要有良好的功能导航能力,还需要在视觉上给人留下深刻印象。

4.2 整体布局结构

首页的布局分为三个区域:

在这里插入图片描述

4.3 数据驱动设计详解

导航卡片使用数据驱动的方式生成,这体现了 ArkUI 声明式 UI 的核心思想——UI 是数据的函数。

首先定义数据模型:

interface NavItem {
title: string; // 布局模式名称
subtitle: string; // 一行精炼描述
features: string[]; // 特点列表(用于卡片中的标签)
gradientStart: string; // 卡片渐变色起点
gradientEnd: string; // 卡片渐变色终点
accentColor: string; // 主题色(用于强调文字和按钮)
icon: string; // Emoji 图标
route: string; // 页面路由路径
}

然后初始化三张卡片的数据:

private readonly navItems: NavItem[] = [
{
title: 'SpaceBetween',
subtitle: '两端对齐 · 首尾贴边',
features: ['首项紧贴容器顶部', '末项紧贴容器底部', '中间项均匀分布'],
gradientStart: '#4F46E5',
gradientEnd: '#7C3AED',
accentColor: '#4F46E5',
icon: '↕️',
route: 'pages/ColumnSpaceBetween'
},
{
title: 'SpaceAround',
subtitle: '环绕分布 · 两端半间距',
features: ['子项两侧环绕空间相等', '两端留白 = 中间间距 / 2', '视觉对称,呼吸感强'],
gradientStart: '#059669',
gradientEnd: '#10B981',
accentColor: '#059669',
icon: '🔄',
route: 'pages/ColumnSpaceAround'
},
{
title: 'SpaceEvenly',
subtitle: '全等间距 · 完全对称',
features: ['所有子项间间距完全相等', '两端留白 = 中间间距', '最均匀的等距分布'],
gradientStart: '#6366F1',
gradientEnd: '#8B5CF6',
accentColor: '#6366F1',
icon: '⚖️',
route: 'pages/ColumnSpaceEvenly'
}
];

最后通过 ForEach 循环渲染所有卡片:

ForEach(this.navItems, (item: NavItem) => {
this.NavCard(item)
})

这种设计模式的精妙之处在于:数据和 UI 完全分离。如果将来需要增加新的布局模式(比如 Row 的三种分布),只需在数组中新增一项,无需改动任何 UI 代码。

4.4 卡片组件的视觉细节

每张卡片使用了多种视觉技术来提升品质感:

(1)渐变色装饰

.linearGradient({
direction: GradientDirection.Left,
colors: [
[item.gradientStart + '08', 0], // 3% 透明度的主题色起始
[item.gradientEnd + '00', 0.95], // 接近完全透明
['#FFFFFF', 1] // 纯白结尾
]
})

这行代码在卡片上覆盖了一层从主题色到透明的渐变,营造出「左侧有彩色装饰条」的视觉效果。+ '08' 是十六进制颜色 alpha 通道的简洁用法,08 表示 8/255 ≈ 3% 透明度。

(2)圆角阴影

.backgroundColor(Color.White)
.borderRadius(20)
.shadow({
radius: 12,
color: '#1A000000', // 10% 透明度黑色阴影
offsetX: 0,
offsetY: 4
})

borderRadius(20) 配合纯白背景,营造出圆角卡片的现代感。shadow() 则让卡片在背景上浮起,形成层次感。

(3)右侧圆形入口按钮

Column() {
Text('→')
.fontSize(22)
.fontColor(item.accentColor)
.fontWeight(FontWeight.Bold)
}
.width(44)
.height(44)
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
.backgroundColor(item.accentColor + '15') // 8% 透明度主题色背景
.borderRadius(22)

44×44 的圆形按钮,背景色为 8% 透明度的主题色,配合右箭头文字,形成一个优雅的视觉入口。

4.5 首页完整源码分析

以下是 Index.ets 的完整 build() 方法结构:

build() {
Column() {
// ═══════════════ ① 页面头部 ═══════════════
Column() {
// 渐变色装饰条(Row()
// .linearGradient(…))
// 应用图标(Text('📐'))
// 主标题(Text('Column 布局方式演示'))
// 副标题(Text('鸿蒙原生 ArkTS 纵向布局'))
// 版本标签(Text('HarmonyOS NEXT API 23+'))
}

// ═══════════════ ② 导航卡片列表 ═══════════════
Scroll() {
Column({ space: 18 }) {
ForEach(this.navItems, (item: NavItem) => {
this.NavCard(item) // 调用 @Builder 方法
})
}
.padding({ left: 20, right: 20, bottom: 20 })
}
.layoutWeight(1) // 占据剩余所有空间

// ═══════════════ ③ 底部信息 ═══════════════
Column({ space: 2 }) {
Text('Column 布局演示应用')
// …
}
}
.width('100%')
.height('100%')
.backgroundColor('#F2F3F8')
}

这里有几个设计细节值得注意:

  • Scroll + layoutWeight(1):让导航卡片区域可以滚动,并占据所有剩余空间。这样在小屏设备上卡片列表可以滚动查看,在平板等大屏设备上则自动撑满。
  • 外层 Column 始终 width('100%').height('100%'):确保根容器撑满全屏,这是所有页面布局的基础。
  • .backgroundColor('#F2F3F8'):浅灰色背景让白色卡片更加突出,形成良好的视觉对比。

五、SpaceBetween:两端对齐 · 首尾贴边

5.1 行为定义

FlexAlign.SpaceBetween 的行为是:第一个子组件紧贴容器顶部,最后一个子组件紧贴容器底部,中间的子组件在剩余空间中均匀分布。容器两端不留空白。

用数学语言描述:假设容器高度为 H,有 n 个子组件,第 i 个子组件的高度为 h_i,则:

  • 第 1 个子组件的顶部 = 0(容器顶部)
  • 第 n 个子组件的底部 = H(容器底部)
  • 第 i 和第 i+1 个子组件之间的间距 = (H – Σh_i) / (n-1)

需要注意的是:当只有 2 个子组件时,SpaceBetween 的效果等价于 Start(首项在顶部,末项在底部,中间项不存在所以没有间距分配)。当只有 1 个子组件时,它会停留在顶部(等同于 Start)。

5.2 适用场景

SpaceBetween 最适合以下场景:

场景一:顶栏 + 内容 + 底栏的典型页面骨架

在大多数应用中,页面结构都是「顶部标题栏 – 中间内容 – 底部操作栏」的经典三段式。使用 SpaceBetween,顶部栏自动贴顶,底部栏自动贴底,中间内容区域自动撑满。

┌──────────────────┐
│ ← 返回 标题 │ ← 贴顶
├──────────────────┤
│ │
│ 主要内容区域 │ ← 自动撑满
│ │
├──────────────────┤
│ 提交 取消 │ ← 贴底
└──────────────────┘

场景二:纵向等分菜单

当需要将几个菜单项在屏幕中均匀分布时,SpaceBetween 可以精确地将它们等间距排列。

场景三:表单的最后操作栏

表单页面底部通常有「提交」和「重置」按钮,使用 SpaceBetween 可以让它们自动分居两端。

5.3 关键源码解析

// ColumnSpaceBetween.ets — 核心布局代码

Column() {
// 顶部块 —— 不受 if 条件影响,始终显示
this.DemoBlock('#3B82F6', '🔝 顶部块(紧贴顶部)', 70)

// 中间块 ① —— 通过 @State 控制显隐
if (this.showMiddleBlock1) {
Column() {
this.DemoBlock('#FF6B6B', '📦 中间块 1(均匀分布)', 70)
}
.width('100%')
.transition({ type: TransitionType.Insert, opacity: 0, translate: { y: 20 } })
.transition({ type: TransitionType.Delete, opacity: 0, translate: { y: 20 } })
}

// 中间块 ② —— 同上
if (this.showMiddleBlock2) {
Column() {
this.DemoBlock('#4ECDC4', '📦 中间块 2(均匀分布)', 70)
}
.width('100%')
.transition({ type: TransitionType.Insert, opacity: 0, translate: { y: 20 } })
.transition({ type: TransitionType.Delete, opacity: 0, translate: { y: 20 } })
}

// 底部块 —— 始终显示
this.DemoBlock('#845EC2', '⬇ 底部块(紧贴底部)', 70)
}
.width('90%')
// ⭐ 核心设置:仅此一行
.justifyContent(FlexAlign.SpaceBetween)
.height(420)
.padding(16)
.border({ width: 2, color: '#E0E7FF', style: BorderStyle.Dashed })
.borderRadius(16)
.backgroundColor('#F8FAFF')
.animation({ duration: 350, curve: Curve.FastOutSlowIn })

代码逐行解读:

  • this.DemoBlock(…) 直接放置,不包裹 if 条件:顶部块和底部块始终存在,确保首尾贴边的视觉效果不会消失。这是 SpaceBetween 布局的关键设计——首和尾是"锚点"。

  • 中间块使用 if 条件包裹:通过 this.showMiddleBlock1 和 this.showMiddleBlock2 两个 @State 变量控制显隐。点击按钮时切换这些变量的值,触发 UI 重渲染。

  • .transition() 动画:出现时从下方 20vp 淡入,消失时向下方 20vp 淡出。这种垂直方向的过渡动画与 Column 的纵向对齐逻辑协调一致。

  • .animation() 容器动画:当中间块数量变化时,SpaceBetween 会重新计算间距并调整布局。.animation() 让这个调整过程平滑过渡,而不是瞬间跳跃。

  • 虚线边框:.border({ style: BorderStyle.Dashed }) 在演示区域周围画一个虚线框,直观地标出容器的边界范围,方便用户理解留白和贴边的概念。

  • 5.4 动态交互演示

    用户界面包含两个控制按钮,分别控制两个中间块的显示:

    Button(this.showMiddleBlock1 ? '隐藏 中间块1' : '显示 中间块1')
    .onClick(() => {
    this.showMiddleBlock1 = !this.showMiddleBlock1;
    })
    .backgroundColor('#FF6B6B')

    Button(this.showMiddleBlock2 ? '隐藏 中间块2' : '显示 中间块2')
    .onClick(() => {
    this.showMiddleBlock2 = !this.showMiddleBlock2;
    })
    .backgroundColor('#4ECDC4')

    按钮的文案跟随状态变化(「隐藏 中间块1」↔「显示 中间块1」),背景色与对应中间块的颜色一致,形成视觉关联。点击后,中间的块会出现或消失,SpaceBetween 会立即重新计算剩余空间的分配,用户可以看到布局从「3个块」变为「2个块」或「4个块」时的自动调整过程。

    这种交互式学习方式比静态截图直观得多——开发者可以亲手操作,亲眼看到布局算法的实时响应。

    5.5 图片预览

    图·布局演示
    在这里插入图片描述
    图·隐藏 中间块1
    在这里插入图片描述
    图·隐藏 中间块2
    在这里插入图片描述


    六、SpaceAround:环绕分布 · 两端半间距

    6.1 行为定义

    FlexAlign.SpaceAround 的行为是:每个子组件两侧的空间(环绕间距)相等。子组件之间的间距是子组件到容器边界间距的两倍。

    数学表达式:假设容器高度为 H,有 n 个子组件,第 i 个子组件的高度为 h_i,则:

    • 第 1 个子组件到容器顶部的间距 = gap/2
    • 第 n 个子组件到容器底部的间距 = gap/2
    • 子组件之间的间距 = gap
    • 其中 gap = (H – Σh_i) / n

    SpaceAround 的名称直译就是「环绕空间的均等分配」——每个子组件周围均匀分布空间,如同行星被轨道环绕。

    6.2 与 SpaceBetween 的对比

    属性SpaceBetweenSpaceAround
    首项到顶部 0(紧贴) gap/2(半间距)
    末项到底部 0(紧贴) gap/2(半间距)
    中间间距 (H-Σh)/(n-1) (H-Σh)/n
    两端视觉 紧凑撑满 留有呼吸空间
    典型感觉 紧绷、拉伸 松弛、透气

    6.3 适用场景

    SpaceAround 在需要视觉"呼吸感"的场景中表现出色:

    场景一:功能按钮组

    假设有 4 个功能按钮需要在页面底部均匀排列。使用 SpaceBetween 会让第一个按钮紧贴左边缘,最后一个紧贴右边缘(在 Row 容器中),看起来过于拥挤。而 SpaceAround 会在两端留出半间距,让按钮组在视觉上更舒适。

    场景二:设置项列表

    在设置页面中,每个设置项之间需要留白以便区分。SpaceAround 可以提供均匀的间距,且两端留白让列表看起来更有边界感。

    场景三:选项卡片

    当多个卡片在容器中纵向排列时,SpaceAround 可以为每张卡片提供等量的上下环绕空间,视觉上更加平衡。

    6.4 关键源码解析

    SpaceAround 的代码结构与 SpaceBetween 类似,核心区别在 justifyContent 一行。

    @Entry
    @Component
    struct ColumnSpaceAroundDemo {
    @State private showMiddleBlock1: boolean = true;
    @State private showMiddleBlock2: boolean = true;
    @State private useFixedHeight: boolean = true;

    build() {
    Column() {
    // ① 标题区
    Text('Column + SpaceAround 布局演示')
    .fontSize(22).fontWeight(FontWeight.Bold)

    // ② 说明文字
    Text('主轴方向:环绕均等分布,两端留白为中间间距的一半')
    .fontSize(14).fontColor('#8891A3')

    // ③ 核心演示区域
    Column() {
    // 顶部块
    this.DemoBlock('#5B8DEF', '🔝 顶部块', 70)

    // 中间块 ①
    if (this.showMiddleBlock1) {
    Column() {
    this.DemoBlock('#FF6B6B', '📦 中间块 1', 70)
    }
    .width('100%')
    .transition({ type: TransitionType.Insert, opacity: 0, translate: { y: 20 } })
    .transition({ type: TransitionType.Delete, opacity: 0, translate: { y: 20 } })
    }

    // 中间块 ②
    if (this.showMiddleBlock2) {
    Column() {
    this.DemoBlock('#4ECDC4', '📦 中间块 2', 70)
    }
    .width('100%')
    .transition({ type: TransitionType.Insert, opacity: 0, translate: { y: 20 } })
    .transition({ type: TransitionType.Delete, opacity: 0, translate: { y: 20 } })
    }

    // 底部块
    this.DemoBlock('#845EC2', '⬇ 底部块', 70)
    }
    .width('90%')
    // ⭐ 核心设置:SpaceAround
    .justifyContent(FlexAlign.SpaceAround)
    .height(this.useFixedHeight ? 460 : 360) // 动态切换高度
    // … 边框、阴影、动画设置

    // ④ 控制按钮区域
    // …
    }
    }
    }

    6.5 高度模式切换的独特设计

    SpaceAround 页面引入了一个 SpaceBetween 没有的功能——「固定高度 / 自适应高度」切换按钮:

    Button(this.useFixedHeight ? '切换到「自适应高度」' : '切换到「固定高度」')
    .onClick(() => {
    this.useFixedHeight = !this.useFixedHeight;
    })

    当 useFixedHeight 为 true 时,容器高度为 460vp;为 false 时降为 360vp。这个设计的目的是:

    • 固定高度模式(460vp):容器有充足的空间,SpaceAround 能清晰展示「两端半间距」的特征。用户可以看到顶部块上方和底部块下方有明显的留白,而且这些留白恰好是中间间距的一半。
    • 自适应高度模式(360vp):容器高度缩小,间距被压缩,两端留白几乎消失。这模拟了实际开发中容器尺寸受约束的情况——当空间不足时,SpaceAround 的效果会退化,看起来接近 Start 对齐。

    这个对比功能帮助开发者理解:空间分布效果依赖于容器有足够的剩余空间。如果容器高度刚好等于所有子组件高度之和(无剩余空间),那么所有三种模式的效果都一样——子组件紧挨在一起。

    6.6 完整的 @Builder DemoBlock

    为了复用代码,三个演示页面共享相同模式的 @Builder 方法:

    @Builder
    DemoBlock(color: string, text: string, height: number) {
    Row() {
    Text(text)
    .fontSize(16)
    .fontColor(Color.White)
    .fontWeight(FontWeight.Medium)
    }
    .width('100%')
    .height(height)
    .backgroundColor(color)
    .borderRadius(12)
    .justifyContent(FlexAlign.Center)
    .shadow({
    radius: 5,
    color: '#33000000',
    offsetX: 0,
    offsetY: 2
    })
    }

    每个块是一个 Row 容器(横向满宽),内部居中显示文字。设置了背景色、圆角和阴影,让每个块看起来像一张独立的卡片。height 参数由调用方传入,保证每个块在演示区域中占据相同的空间,便于观察间距变化。

    6.7 图片预览

    图·布局演示
    在这里插入图片描述
    图·隐藏 中间块1
    在这里插入图片描述

    图·隐藏 中间块2
    在这里插入图片描述

    图·切换到“自适应高度”
    在这里插入图片描述


    七、SpaceEvenly:全等间距 · 完全对称

    7.1 行为定义

    FlexAlign.SpaceEvenly 的行为是:所有在主轴方向上的空隙——包括首项到容器顶部、子组件之间、末项到容器底部——完全相等。

    数学表达式:假设容器高度为 H,有 n 个子组件,第 i 个子组件的高度为 h_i,则:

    • 首项到容器顶部间距 = gap
    • 末项到容器底部间距 = gap
    • 子组件之间的间距 = gap
    • 其中 gap = (H – Σh_i) / (n+1)

    SpaceEvenly 是三种模式中数学最对称的一种,它将容器空间均匀切分为 n+1 个等份,子组件位于这些等份之间的分隔线上,而非等份内部。

    7.2 适用场景

    SpaceEvenly 最适合需要严格对称、视觉平衡的场景。

    场景一:导航标签栏

    当希望所有导航标签在垂直方向上均匀分布时,SpaceEvenly 可以让标签之间的间距和标签到两端的间距完全一致,视觉效果最为平衡。

    场景二:步骤指示器

    在注册流程、引导页等多步骤界面中,SpaceEvenly 可以均匀分布每个步骤点,且首尾到边界的留白让步骤不会紧贴屏幕边缘。

    场景三:评分或星级显示

    当显示 5 颗星的评分时,SpaceEvenly 可以确保星星之间的间距和星星到容器边界的间距一致,视觉均衡。

    7.3 关键源码解析

    SpaceEvenly 页面是三个演示中最复杂的——它支持 3 个中间块的显隐控制:

    @Entry
    @Component
    struct ColumnSpaceEvenlyDemo {
    @State private showMiddleBlock1: boolean = true;
    @State private showMiddleBlock2: boolean = true;
    @State private showMiddleBlock3: boolean = true;
    @State private useFixedHeight: boolean = true;

    build() {
    Column() {
    // ① 页面标题
    Text('Column + SpaceEvenly 布局演示')
    .fontSize(22).fontWeight(FontWeight.Bold)

    // ② 布局说明
    Text('主轴方向:完全等间距分布(两端间距 = 中间间距)')
    .fontSize(14)

    // ③ 核心演示区域
    Column() {
    // 顶部块
    this.DemoBlock('#6366F1', '🔝 顶部块', 64)

    // 中间块 A(showMiddleBlock1)
    if (this.showMiddleBlock1) {
    Column() {
    this.DemoBlock('#F59E0B', '📦 中间块 A', 64)
    }
    .width('100%')
    .transition({ type: TransitionType.Insert, opacity: 0, translate: { y: 20 } })
    .transition({ type: TransitionType.Delete, opacity: 0, translate: { y: 20 } })
    }

    // 中间块 B(showMiddleBlock2)
    if (this.showMiddleBlock2) {
    Column() {
    this.DemoBlock('#10B981', '📦 中间块 B', 64)
    }
    .width('100%')
    .transition({ type: TransitionType.Insert, opacity: 0, translate: { y: 20 } })
    .transition({ type: TransitionType.Delete, opacity: 0, translate: { y: 20 } })
    }

    // 中间块 C(showMiddleBlock3)
    if (this.showMiddleBlock3) {
    Column() {
    this.DemoBlock('#F43F5E', '📦 中间块 C', 64)
    }
    .width('100%')
    .transition({ type: TransitionType.Insert, opacity: 0, translate: { y: 20 } })
    .transition({ type: TransitionType.Delete, opacity: 0, translate: { y: 20 } })
    }

    // 底部块
    this.DemoBlock('#8B5CF6', '⬇ 底部块', 64)
    }
    .width('90%')
    // ⭐ 核心设置:SpaceEvenly
    .justifyContent(FlexAlign.SpaceEvenly)
    .height(this.useFixedHeight ? 500 : 400)
    // … 边框、阴影、动画设置

    // ④ 控制区域(3 个按钮 + 高度切换)
    // …
    }
    }
    }

    7.4 三个中间块带来的丰富组合

    SpaceEvenly 页面支持 3 个中间块,意味着有 2³ = 8 种组合状态。用户可以通过 3 个独立的按钮来控制每个块的显隐:

    Row({ space: 10 }) {
    Button(this.showMiddleBlock1 ? '隐藏 A' : '显示 A')
    .onClick(() => { this.showMiddleBlock1 = !this.showMiddleBlock1; })
    .backgroundColor('#F59E0B')

    Button(this.showMiddleBlock2 ? '隐藏 B' : '显示 B')
    .onClick(() => { this.showMiddleBlock2 = !this.showMiddleBlock2; })
    .backgroundColor('#10B981')

    Button(this.showMiddleBlock3 ? '隐藏 C' : '显示 C')
    .onClick(() => { this.showMiddleBlock3 = !this.showMiddleBlock3; })
    .backgroundColor('#F43F5E')
    }

    从「全部显示(5 个块)」到「全部隐藏(2 个块)」,用户可以清晰地看到 SpaceEvenly 如何自动重新计算所有间隙(包括两端),使得无论有多少个块,所有空隙始终保持相等。

    7.5 图片预览

    图·布局演示
    在这里插入图片描述
    图·隐藏 A
    在这里插入图片描述

    图·隐藏 B
    在这里插入图片描述

    图·隐藏 C
    在这里插入图片描述

    图·切换到“自适应高度”
    在这里插入图片描述


    八、三种模式的实战对比

    8.1 对比表格

    每个演示页面底部都附有一个完整的三种布局对比表格(以 SpaceBetween 页面为例):

    // 表头
    Row() {
    Text('模式').width(100)
    Text('首项贴顶').width(70)
    Text('末项贴底').width(70)
    Text('两端留白').width(70)
    }

    // SpaceBetween 行(高亮显示)
    Row() {
    Text('SpaceBetween').fontColor('#3B82F6').fontWeight(FontWeight.Bold)
    Text('✅').width(70)
    Text('✅').width(70)
    Text('❌').width(70).fontColor('#8891A3')
    }
    .backgroundColor('#EFF6FF') // 浅蓝色背景高亮当前模式

    // SpaceAround 行
    Row() {
    Text('SpaceAround')
    Text('❌').width(70)
    Text('❌').width(70)
    Text('半间距').width(70).fontColor('#059669')
    }

    // SpaceEvenly 行
    Row() {
    Text('SpaceEvenly')
    Text('❌').width(70)
    Text('❌').width(70)
    Text('等间距').width(70).fontColor('#6366F1')
    }

    表格使用 Row + Text 模拟实现,每行对应一种布局模式。当前正在演示的模式(每个页面对应的模式)会高亮显示——背景色变为浅色调,文字加粗变色。这种设计让用户在操作时能立即定位到表格中的对应行,强化理解。

    8.2 综合对比分析

    对比维度SpaceBetweenSpaceAroundSpaceEvenly
    首项位置 紧贴容器顶部 距离顶部 gap/2 距离顶部 gap
    末项位置 紧贴容器底部 距离底部 gap/2 距离底部 gap
    中间间距大小 (H-Σh)/(n-1) (H-Σh)/n (H-Σh)/(n+1)
    两端留白 无(0) 半间距(gap/2) 等间距(gap)
    n=2 时的行为 首贴顶,末贴底 首距顶 gap/2,末距底 gap/2 首距顶 gap,末距底 gap
    n=1 时的行为 子项在顶部(=Start) 子项居中(=Center) 子项居中(=Center)
    视觉特征 紧凑、拉伸、撑满 透气、留白、呼吸感 对称、均衡、规律
    适用布局 页眉+内容+页脚 按钮组、卡片列表 导航栏、评分指示器

    8.3 选型决策树

    在实际项目中,可以用这个决策树快速选择合适的模式:

    Q1:容器是否有固定高度或明确的空间约束?
    ├── 否 → 三种模式都可能退化(无剩余空间),优先考虑用 Start/Center
    │ 或给容器设置 minHeight 确保有空间分配
    └── 是 → 进入 Q2

    Q2:是否希望首项和末项贴边?
    ├── 是 → SpaceBetween
    │ 典型场景:页面顶部标题栏 + 底部操作栏
    └── 否 → 进入 Q3

    Q3:是否希望两端留白?
    ├── 是,但少量留白(半间距)→ SpaceAround
    │ 典型场景:功能按钮组、设置项列表
    └── 是,完全等间距 → SpaceEvenly
    典型场景:导航标签、步骤指示器

    8.4 一个具体的实战案例

    假设需要实现一个登录页面:

    ┌──────────────────────┐
    │ 欢迎回来 │ ← 顶部欢迎语
    ├──────────────────────┤
    │ │
    │ 📱 手机号输入框 │
    │ 🔒 密码输入框 │
    │ │
    │ [登录] [注册] │
    │ │
    ├──────────────────────┤
    │ 遇到问题?联系客服 │ ← 底部帮助链接
    └──────────────────────┘

    分析需求:

    • 顶部欢迎语 → 需要贴顶 → ✅
    • 中部输入框和按钮 → 在中间区域均匀分布
    • 底部帮助链接 → 需要贴底 → ✅

    最佳选择: SpaceBetween。顶部紧贴顶部,底部紧贴底部,中间内容在剩余空间中均匀分布。这正是 SpaceBetween 最经典的「三段式布局」用法。

    Column() {
    Text('欢迎回来')
    .fontSize(24)
    .fontWeight(FontWeight.Bold)

    // 中间内容区域,在剩余空间中均匀分布
    Column() {
    TextInput({ placeholder: '手机号' })
    TextInput({ placeholder: '密码' })
    .type(InputType.Password)
    Row({ space: 16 }) {
    Button('登录').type(ButtonType.Capsule)
    Button('注册').type(ButtonType.Capsule)
    }
    }
    .layoutWeight(1)
    .justifyContent(FlexAlign.SpaceEvenly)

    Text('遇到问题?联系客服')
    .fontSize(12).fontColor('#999')
    }
    .height('100%')
    .justifyContent(FlexAlign.SpaceBetween)

    这个案例展示了两种 justifyContent 的嵌套使用:外层 Column 用 SpaceBetween 实现「首尾贴边」,内层中间区域用 SpaceEvenly 实现「内容均匀分布」。


    九、实战经验与常见陷阱

    9.1 @Builder 的 void 返回值陷阱

    这是本项目中最常遇到的问题,值得重点强调。

    问题现象:

    // ColumnSpaceBetween.ets 第 72 行
    if (this.showMiddleBlock1) {
    this.DemoBlock('#FF6B6B', '📦 中间块 1(均匀分布)', 70)
    .transition({ type: TransitionType.Insert, opacity: 0 }) // 编译报错!
    }

    编译时报错:Property 'transition' does not exist on type 'void'

    原因分析:

    ArkTS 中 @Builder 装饰的方法是一个特殊的语法结构,它的返回值类型被定义为 void。这意味着你不能在 @Builder 调用结果上链式调用组件的方法(如 .transition()、.width()、.height() 等)。这不是一个 Bug,而是 ArkTS 语言的有意设计——@Builder 方法生成的是一个构建块(buildable block),而不是一个组件实例。

    解决方案:

    在外层包裹一个容器组件,在容器上调用链式方法:

    if (this.showMiddleBlock1) {
    Column() {
    this.DemoBlock('#FF6B6B', '📦 中间块 1(均匀分布)', 70)
    }
    .width('100%') // ✅ 在 Column 上调用
    .transition({ // ✅ 在 Column 上调用
    type: TransitionType.Insert,
    opacity: 0,
    translate: { y: 20 }
    })
    .transition({
    type: TransitionType.Delete,
    opacity: 0,
    translate: { y: 20 }
    })
    }

    这个方法的好处是:外层 Column 不仅可以承载 .transition(),还可以设置 .width('100%') 确保子组件撑满宽度,一举两得。

    9.2 Color 枚举兼容性问题

    问题现象:

    .backgroundColor(Color.LightGray) // 编译报错:Property 'LightGray' does not exist

    原因分析:

    HarmonyOS NEXT API 23 的 Color 枚举中,并不是所有直觉上的颜色都存在。经过实际测试,以下颜色在 API 23 中不可用:

    不可用枚举可用的替代方案
    Color.LightGray '#D0D0D0'
    Color.DarkGray '#555555' 或 '#666666'
    Color.Gray '#808080'
    Color.LightBlue '#E0E7FF'
    Color.DarkBlue '#1E3A5F'
    Color.LightGreen '#D1FAE5'
    Color.DarkGreen '#065F46'
    Color.LightRed '#FEE2E2'

    最佳实践:统一使用十六进制字符串色值 '#RRGGBB' 或 '#AARRGGBB',避免依赖 Color 枚举中可能缺失的成员。字符串色值在所有 API 版本中都兼容,且支持 alpha 通道(通过 8 位色值 '#AARRGGBB' 实现透明度)。

    // ✅ 推荐做法:使用字符串色值
    .backgroundColor('#D0D0D0') // LightGray
    .backgroundColor('#F0F0F0') // 更浅的灰色
    .backgroundColor('#F8FAFF') // 非常浅的蓝色调
    .backgroundColor('#1A1A2E') // 深色文字
    .backgroundColor('#8891A3') // 灰色文字
    .backgroundColor('#E0E7FF') // 浅蓝色边框

    // 如果需要透明度:使用 8 位色值(前两位为 alpha)
    .backgroundColor('#33000000') // 20% 透明的黑色(阴影颜色)
    .backgroundColor('#E0E7FF') // 完全不透明
    .backgroundColor('#1A000000') // 10% 透明的黑色
    .backgroundColor('#08' + '#4F46E5') // 3% 透明度的主题色(拼接方式)

    9.3 容器高度与空间分布的关系

    一个容易被忽略的点:当容器没有固定高度时,三种分布模式的效果相同。

    这是因为:

    • Column 的默认高度由其子组件的高度之和决定(wrap_content 行为)
    • 如果容器高度 = 子组件高度之和,则剩余空间 = 0
    • 剩余空间 = 0 时,所有分布模式都没有空间可以分配
    • 子组件之间没有间距,首尾也没有留白

    // ❌ 这样的 SpaceEvenly 没有效果(容器高度由内容决定)
    Column() {
    Text('A')
    Text('B')
    Text('C')
    }
    .justifyContent(FlexAlign.SpaceEvenly)
    // 没有设置 .height(),也没有设置 .layoutWeight(1)
    // 结果:三个文字紧挨在一起,SpaceEvenly 无效

    解决方案:

    // ✅ 方案一:设置固定高度
    Column() {
    // …
    }
    .justifyContent(FlexAlign.SpaceEvenly)
    .height(400) // 固定高度,框架有空间进行计算

    // ✅ 方案二:使用 layoutWeight 撑满父容器
    Column() {
    // …
    }
    .layoutWeight(1) // 占据父容器所有剩余空间
    .justifyContent(FlexAlign.SpaceBetween)

    // ✅ 方案三:使用百分比高度
    Column() {
    // …
    }
    .height('100%') // 撑满父容器
    .justifyContent(FlexAlign.SpaceAround)

    在实际项目中,方案二(layoutWeight)是最推荐的,因为它既不需要固定高度,又能确保容器有足够的空间来执行分布算法。

    9.4 深色模式适配

    本项目通过资源限定词实现了深色模式适配:

    亮色模式颜色(resources/base/element/color.json):

    {
    "color": [
    { "name": "start_window_background", "value": "#FFFFFF" }
    ]
    }

    深色模式颜色(resources/dark/element/color.json):

    {
    "color": [
    { "name": "start_window_background", "value": "#000000" }
    ]
    }

    HarmonyOS 的资源管理系统会自动根据系统的深色/亮色模式加载对应的资源文件。如果希望代码中也能感知颜色模式,可以通过 ConfigurationConstant.ColorMode 进行判断:

    // EntryAbility.ets
    import { AbilityConstant, ConfigurationConstant } from '@kit.AbilityKit';

    onCreate(want, launchParam) {
    // 设置为跟随系统(默认行为)
    this.context.getApplicationContext()
    .setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
    }

    9.5 性能优化建议

    虽然这个项目是一个轻量级演示应用,但在实际复杂项目中,以下优化建议值得注意:

    1. 避免过度使用动画

    .animation() 和 .transition() 虽然体验好,但每次状态变化都会触发布局重算和动画帧渲染。对于大量列表项(比如 100+ 个子组件),建议仅在明确需要动画的场景使用这些 API。

    2. @State 粒度的控制

    @State 变量的粒度应尽可能精细。例如,控制三个中间块显示使用三个独立的 @State 变量 showMiddleBlock1、showMiddleBlock2、showMiddleBlock3,而不是用一个 number 类型表示状态组合。这样当某个块变化时,只有相关的 UI 部分会重渲染。

    3. 合理使用 @Builder

    对于复用性高的 UI 片段,使用 @Builder 而不是 @Component 可以减少组件树的深度,提高渲染性能。


    十、项目工程化最佳实践

    10.1 模块配置

    项目的 entry/src/main/module.json5 配置了模块的基本信息:

    {
    module: {
    name: 'entry',
    type: 'entry',
    srcEntry: './ets/entryability/EntryAbility.ets',
    description: 'Column布局演示',
    abilities: [
    {
    name: 'EntryAbility',
    srcEntry: './ets/entryability/EntryAbility.ets',
    launchType: 'standard',
    // …
    }
    ]
    }
    }

    这里 launchType: 'standard' 表示每次启动都创建新的 Ability 实例。

    10.2 页面路由注册

    所有页面需要在 main_pages.json 中注册:

    {
    "src": [
    "pages/Index",
    "pages/ColumnSpaceBetween",
    "pages/ColumnSpaceAround",
    "pages/ColumnSpaceEvenly"
    ]
    }

    router.pushUrl({ url: 'pages/ColumnSpaceBetween' }) 会自动匹配这里的注册信息进行页面跳转。

    10.3 应用包配置

    AppScope/app.json5 定义了应用级别的信息:

    {
    app: {
    bundleName: 'com.example.columnlayoutdemo',
    vendor: 'YourCompany',
    version: {
    code: 1,
    name: '1.0.0'
    },
    apiVersion: {
    compatible: 23,
    target: 23
    }
    }
    }

    apiVersion.compatible 和 apiVersion.target 分别指定了兼容的最低 API 版本和目标 API 版本。本项目设为 23(HarmonyOS NEXT)。

    10.4 .gitignore 配置

    项目中应该包含 .gitignore 来屏蔽不需要提交的文件:

    # 本地配置
    local.properties

    # 构建输出
    build/
    entry/build/

    # IDE 配置
    .idea/
    *.iml

    # 包管理器
    oh_modules/
    node_modules/


    十一、总结

    11.1 核心收获

    通过这个项目的开发和本文的详细解析,我们系统性地学习了鸿蒙 ArkUI 中 Column 容器的三种主轴分布模式:

    模式一句话概括间距公式最佳场景
    SpaceBetween 首尾贴边,中间均匀 gap = (H-Σh)/(n-1) 三段式页面
    SpaceAround 两端半间距,中间等距 gap = (H-Σh)/n 按钮组、卡片列表
    SpaceEvenly 所有空隙完全相等 gap = (H-Σh)/(n+1) 导航栏、步骤指示器

    11.2 项目质量保障

    在开发中,我们坚持了以下原则:

    • 零第三方依赖:所有代码仅使用 ArkUI 内置 API
    • 类型安全:使用 string 色值而非可能缺失的 Color 枚举
    • 充分注释:每个文件含有中英双语注释、ASCII 示意图
    • 交互体验:动画过渡、动态控制、实时反馈
    • API 兼容性:确保所有 API 调用在 API 23 以上版本正常运行

    11.3 未来拓展方向

    该项目仍有广阔的功能拓展空间:

  • 增加 Row 容器演示:对比 Column 和 Row 在主轴方向上的差异
  • 实现 alignSelf 演示:展示单个子组件在交叉轴上的独立对齐
  • 引入 wrap 换行:当子组件过多时自动换行显示
  • 嵌套布局演示:展示 Column + Row 复杂嵌套构建真实页面
  • 主题自定义:让用户自由切换配色方案
  • 国际化支持:通过 $r 引用字符串资源实现多语言
  • 11.4 致谢与展望

    鸿蒙生态正在以前所未有的速度成长。从最初的兼容 Android 到今天的「纯血鸿蒙」,华为用短短几年走完了其他操作系统十几年的路。作为开发者,我们有幸见证并参与这个历史进程。

    ArkUI 和 ArkTS 的组合,让鸿蒙原生开发拥有了不亚于 SwiftUI + Swift、Flutter + Dart 的开发体验。声明式 UI 的简洁、强类型语言的安全、以及华为强大的硬件生态,都为鸿蒙原生应用的发展奠定了坚实的基础。

    如果你正在学习鸿蒙开发,希望本文的代码示例和实战经验能对你有所帮助。记住:布局是 UI 的骨架,理解 flex 布局的精髓,才能构建出优雅的界面。 在实践中多动手、多尝试、多思考,你会发现 ArkUI 的魅力所在。

    最后,再次感谢「鸿蒙原生 ArkTS 布局实战」征文活动提供的分享平台。期待与更多开发者一起交流鸿蒙开发经验,共同推动鸿蒙生态的繁荣发展!


    附录 A:完整项目源码速查

    A.1 文件清单

    文件相对路径行数功能
    pages/Index.ets ~247 导航首页,三张卡片入口
    pages/ColumnSpaceBetween.ets ~271 SpaceBetween 交互式演示
    pages/ColumnSpaceAround.ets ~282 SpaceAround 交互式演示
    pages/ColumnSpaceEvenly.ets ~288 SpaceEvenly 交互式演示
    entryability/EntryAbility.ets ~48 应用入口 Ability
    resources/base/element/color.json ~8 基础颜色资源
    resources/base/element/string.json ~10 字符串资源
    resources/base/profile/main_pages.json ~6 页面路由注册
    resources/dark/element/color.json ~8 深色模式颜色

    A.2 关键 API 速查表

    API类型用途关键参数
    .justifyContent(flexAlign) Column / Row 设置主轴对齐方式 FlexAlign.SpaceBetween / SpaceAround / SpaceEvenly
    .animation(params) 通用组件 布局变化自动动画 { duration: 350, curve: Curve.FastOutSlowIn }
    .transition(params) 通用组件 元素出现/消失动画 { type: TransitionType.Insert, opacity: 0, translate: { y: 20 } }
    router.pushUrl(obj) router API 页面路由跳转 { url: 'pages/ColumnSpaceBetween' }
    .linearGradient(obj) 通用组件 线性渐变背景 { direction, colors: [color,offset][] }
    .shadow(obj) 通用组件 阴影效果 { radius, color, offsetX, offsetY }
    .layoutWeight(n) 通用组件 弹性占据剩余空间 正整数
    .border(obj) 通用组件 边框 { width, color, style: BorderStyle.Dashed }
    @State 装饰器 声明响应式状态变量 变量变化自动触发 UI 重渲染
    @Builder 装饰器 声明可复用的构建方法 返回 void,需容器包裹调用链式方法
    ForEach(arr, fn) 循环组件 数组遍历渲染 (item, index) => { Component }

    本文参与「鸿蒙原生 ArkTS 布局实战」征文活动
    开发环境:HarmonyOS NEXT (API 23+) | DevEco Studio 5.0+
    项目源码:GitHub — harmonyOSZhengWen
    欢迎 Star、Fork、Issue 交流!

    赞(0)
    未经允许不得转载:171主机测评 » 【共创季稿事节】鸿蒙原生 ArkTS 布局实战:Column 主轴三种分布模式(SpaceBetween / SpaceAround / SpaceEvenly)深度解析
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址