【OpenHarmony/HarmonyOs 】ArkUI 设计系统入门:用 UiTokens 统一颜色、间距、圆角与阴影
【OpenHarmony/HarmonyOs 】ArkUI 设计系统入门:用 UiTokens 统一颜色、间距、圆角与阴影
前言
当页面从一个增长到六个时,直接写颜色和尺寸会迅速失控:同样的灰色出现多个值,同级卡片圆角不同,修改品牌色需要全项目搜索。LinkOS 链界建立了一个轻量 UiTokens,把视觉常量集中管理。本文介绍这种做法,并进一步讨论深色模式、资源系统和多设备响应式布局。🎨
一、什么是 Design Token
Design Token 是设计决策的代码化表达。它不描述“某个按钮宽 44”,而描述“中号圆角”“主色”“弱文本色”等可复用语义。
export class UiTokens {
static readonly COLOR_PRIMARY = '#0A59F7';
static readonly COLOR_BG = '#F7F8FA';
static readonly COLOR_CARD = '#FFFFFF';
static readonly COLOR_TEXT = '#0B1220';
static readonly COLOR_TEXT_MUTED = '#6B7280';
static readonly COLOR_BORDER = '#EEF0F4';
static readonly RADIUS_SM = 10;
static readonly RADIUS_MD = 14;
static readonly RADIUS_LG = 18;
static readonly RADIUS_XL = 24;
static readonly SPACE_8 = 8;
static readonly SPACE_12 = 12;
static readonly SPACE_16 = 16;
static readonly SPACE_24 = 24;
}
页面使用语义常量后,设计语言更统一:
Column() { /* 卡片内容 */ }
.padding(UiTokens.SPACE_16)
.backgroundColor(UiTokens.COLOR_CARD)
.borderRadius(UiTokens.RADIUS_LG)
.border({ width: 1, color: UiTokens.COLOR_BORDER })
.shadow(UiTokens.SHADOW_SM)
二、阴影也需要结构化
export interface ShadowToken {
radius: number;
color: string;
offsetX?: number;
offsetY?: number;
}
static readonly SHADOW_SM: ShadowToken = {
radius: 6,
color: 'rgba(15, 23, 42, 0.06)',
offsetY: 2
};
把阴影作为一个整体 Token,可以保证 radius、透明度和偏移不会被随意组合。建议只保留少量阴影层级:普通卡片、浮层、模态框。层级越多,界面越容易显得杂乱。
三、Builder 是轻量组件化工具
页面中反复出现标签、统计卡、导航项,可以使用 @Builder:
@Builder
StatsCard(title: string, value: string) {
Column() {
Text(value)
.fontSize(18)
.fontWeight(FontWeight.Bold)
Text(title)
.fontSize(11)
.fontColor(UiTokens.COLOR_TEXT_MUTED)
}
.height(60)
.backgroundColor(UiTokens.COLOR_CARD)
.borderRadius(UiTokens.RADIUS_LG)
}
Builder 适合同一页面内部的重复结构。若组件跨页面复用、拥有独立状态或生命周期,应提取为独立 @Component 文件。例如当前四个主页面都实现了类似底部导航,后续最好统一为公共组件,避免修改一处却遗漏其他页面。
四、两列 Grid 只是响应式起点
欢迎页和元服务页使用:
Grid() { /* items */ }
.columnsTemplate('1fr 1fr')
.columnsGap(12)
.rowsGap(12)
两列在手机上合适,但项目声明支持 phone、tablet、2in1,固定两列会浪费宽屏空间。响应式设计应根据窗口宽度切换布局:
< 600vp 2 列,底部导航
600-840vp 3 列,内容区适度加宽
> 840vp 4 列或侧边导航,限制正文最大宽度
宽屏适配不是把所有元素同比放大。正确做法通常是增加列数、提高信息密度、限制内容最大宽度,并让导航位置更符合大屏操作。
五、安全区与底部导航
底部导航调用:
.expandSafeArea(
[SafeAreaType.SYSTEM],
[SafeAreaEdge.BOTTOM]
)
这能处理手势导航区域与设备底部差异。欢迎页同时扩展顶部和底部背景,使渐变铺满屏幕,但内容仍应保留足够 padding。背景扩展和可交互内容避让是两个不同概念。
六、深色模式不能只准备一个资源目录
项目已有 resources/dark/element/color.json,但不少页面仍直接写十六进制颜色。硬编码颜色不会自动响应深色资源。
要真正支持深色模式,应逐步将语义颜色迁移为资源:
.backgroundColor($r('app.color.page_background'))
.fontColor($r('app.color.text_primary'))
系统切换配置后,资源系统会选择对应限定目录。品牌渐变、插图等少量特殊颜色可以保留 Token,但文本、背景、边框等基础语义最好资源化。
七、文字与本地化
直接写中文便于原型开发,但语言切换仅保存 zh-CN/en-US 并不会自动改变页面文本。完整国际化需要:
- 把字符串放入
resources/base/element/string.json; - 增加语言限定资源;
- 页面通过
$r('app.string.xxx')引用; - 切换语言时更新应用配置或重新加载相关页面;
- 检查英文变长后卡片和按钮是否溢出。
八、视觉一致性检查清单
- 同层级标题是否使用相同字号与字重;
- 卡片是否只使用有限的圆角层级;
- 文本和背景对比度是否足够;
- 所有点击目标是否有稳定尺寸;
- 长标题是否设置
maxLines与省略; - 手机、平板、横屏是否没有重叠;
- 深色模式下边框和阴影是否仍然自然;
- 动画和颜色是否照顾减少动态效果与色觉差异用户。
九、总结
设计系统不一定从庞大的组件库开始。先统一颜色、间距、圆角和阴影,再用 Builder 消除页面内重复,用公共组件解决跨页面一致性,最后结合资源限定目录实现深色与国际化,就能让 ArkUI 项目从“每页各写各的”逐步走向稳定的产品界面。✅


更多推荐

所有评论(0)