从 Android 转到 HarmonyOS 做 UI,你最容易掉进两个坑:
1) 把 ArkUI 当成“换皮的 Compose”,看到 Column() 就以为完全等价。 2) 把 ArkUI 当成“更像 XML 的 UI DSL”,结果写着写着全是样式与逻辑混在一起,复用边界越来越糊。
这篇文章先做两件事:把布局容器(Row/Column/Stack)和“属性链”这种写法对齐,然后用一个最小“第一屏骨架”把常用写法跑通。你不需要记住所有控件,你只需要先抓住 4 个能力:
- 用什么容器组织结构(Row/Column/Stack)
- 用什么方式施加样式与交互(属性链 / Modifier)
- 如何表达间距与对齐(padding/margin/alignment)
- 如何把 UI 拆成可复用块(组件边界)
一张对照表:把“布局容器 + 修饰方式”先对齐
> 备注:文中会拿 Jetpack Compose 做对照。Compose 是 Android 官方的声明式 UI 框架,你可以把它理解为“用 Kotlin 直接写 UI 组件”,不再用 XML 布局。即使你不熟 Compose,也不影响你读这篇:你只需要把它当成一套更接近 ArkUI 的对照参照物。
如果你只看 API 名字,很容易误判。更好的做法是按“工程动作”对齐:你在写 UI 的时候到底在做什么。
| 你在做的事 | Android(Compose) | HarmonyOS(ArkUI / ArkTS) | 迁移时应该保留的心智 |
|---|---|---|---|
| 纵向堆叠 | Column { ... } |
Column() { ... } |
结构先行:先定层级,再补样式 |
| 横向排列 | Row { ... } |
Row() { ... } |
主轴/交叉轴:对齐与间距归主容器管 |
| 叠层/覆盖 | Box { ... } |
Stack() { ... } |
叠层一定要控边界:谁负责点击/谁负责背景 |
| 给组件加样式 | Modifier.padding().background() |
.padding().background()(属性链) |
样式是“可组合的修饰”,不要写成散落的 if/else |
| 给组件加交互 | Modifier.clickable { } |
.onClick(() => {}) |
交互属于组件本身:别把点击绑在“外层容器”偷懒 |
| 控制尺寸 | fillMaxWidth() / width() |
.width('100%') / .width(…) |
先用约束表达意图:填充/固定/自适应 |
这里最关键的一点是:ArkUI 的“属性链”不是样式拼接技巧,而是组件可读性的核心。 它对应的是 Compose 里 Modifier 的那条链路:把一个组件的“结构 + 外观 + 交互”收敛成一个局部可理解的单元。
用一个“第一屏骨架”把关键点跑通:卡片列表 + 顶部信息区
我们用一个很常见的第一屏:上面是标题与说明,下面是两张卡片(可点击),外层有统一间距与背景。这个例子刻意只用最基础的容器与属性,不引入状态管理与导航,避免一上来变成框架课。
HarmonyOS(ArkUI / ArkTS)写法(骨架示例)
@Component
struct HomeScreen {
build() {
Column() {
Column() {
Text('Welcome')
.fontSize(24)
.fontWeight(FontWeight.Bold)
Text('把第一屏先搭出来,再谈迁移与复用。')
.fontSize(14)
.opacity(0.75)
.margin({ top: 6 })
}
.alignItems(HorizontalAlign.Start)
.padding(16)
Column() {
EntryCard({ title: '快速开始', desc: 'Row/Column/Stack 的最小闭环' })
EntryCard({ title: '布局对照', desc: 'Compose vs ArkUI 的工程语义' })
}
.padding({ left: 16, right: 16, bottom: 16 })
}
.width('100%')
.height('100%')
.backgroundColor('#F6F7F9')
}
}
@Component
struct EntryCard {
title: string = ''
desc: string = ''
build() {
Column() {
Text(this.title).fontSize(16).fontWeight(FontWeight.Medium)
Text(this.desc).fontSize(12).opacity(0.7).margin({ top: 6 })
}
.width('100%')
.padding(14)
.backgroundColor(Color.White)
.borderRadius(12)
.margin({ top: 12 })
.onClick(() => {
// TODO: 这里后续接路由(Want / navigation)
})
}
}
显示效果(示意图):

这个骨架里有三个点建议你立刻养成习惯:
1) 外层 Column 管“页面级布局”:背景、全屏尺寸、整体 padding。 2) 卡片组件自己负责点击与样式:不要把点击事件放到外层列表里“顺手绑一下”。 3) 属性链按“从结构到细节”的顺序写:尺寸/间距 → 背景/圆角 → 交互,这样读起来像一条完整句子。
Android(Compose)对照写法(同等骨架)
@Composable
fun HomeScreen() {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color(0xFFF6F7F9))
) {
Column(
modifier = Modifier.padding(16.dp),
horizontalAlignment = Alignment.Start
) {
Text("Welcome", fontSize = 24.sp, fontWeight = FontWeight.Bold)
Text(
"把第一屏先搭出来,再谈迁移与复用。",
fontSize = 14.sp,
modifier = Modifier.padding(top = 6.dp),
alpha = 0.75f
)
}
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
EntryCard("快速开始", "Row/Column/Stack 的最小闭环") { /* TODO */ }
EntryCard("布局对照", "Compose vs ArkUI 的工程语义") { /* TODO */ }
}
}
}
从界面看两边实现效果一致(示意图):

你会发现:两边真正一致的是工程组织方式——“页面容器 + 可复用卡片组件 + 修饰链”。差异更多体现在 API、单位体系与默认行为上。
学习时最常见的三个误区(以及更推荐的写法)
误区 1:把所有样式提到最外层,导致复用崩溃
常见症状:卡片看起来相似,但每张卡片都有一点点差异,你把差异都做成外层的条件分支,最后组件失去边界。
更推荐的做法:“组件先自洽”。卡片组件内部先把 padding/圆角/背景/点击写完整;外层只决定“排布关系”(间距、列表结构),不要决定卡片的皮肤。
误区 2:过早引入状态管理,把布局学习变成框架学习
这一篇先不展开 @State、@Link、@Observed 这类状态装饰器。先把“容器怎么嵌套、属性链怎么写、组件边界怎么划分”写顺,再把状态作为下一层能力补进来,会更容易复现和定位问题。
误区 3:用“像不像 Compose”判断写法对不对
关键不是“写法像 Compose”,而是“工程语义是否成立”:组件是否可读、是否可复用、是否能被测试、是否能被定位问题。
Checklist:把 ArkUI 第一屏从“能跑”升级到“可维护”
当你把第一屏搭出来后,建议按这份 checklist 做一次自检(两边通用):
1) 结构:页面容器与卡片组件边界清晰(外层管布局,组件内管皮肤与交互) 2) 修饰链:同一组件的样式集中在一条链上(不要散落在多个分支里) 3) 间距体系:padding/margin 有固定刻度(8/12/16…),避免“到处是 13/15/17” 4) 点击区域:可点击区域与视觉区域一致(不要出现“看得见但点不到/点到别的”) 5) 回归点:至少能用 2–3 条用例回归(展示正确、点击正确、列表滚动不抖动)
参考素材
- Android(官方):Compose 布局基础(Row/Column/Box):https://developer.android.com/develop/ui/compose/layouts/basics
- Android(官方):Modifier(修饰链的核心入口):https://developer.android.com/develop/ui/compose/modifiers
- HarmonyOS(官方):ArkUI 布局基础与容器组件(Row/Column/Stack):https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-ui-layout-overview-0000001774110449
// Kai@CodeHubble // 观测坐标:Android-HarmonyOS/2026-05-14