引子:五个工具,一套视觉语言

小工具百宝箱有五个工具——二维码、单位换算、随机决策、颜色提取、倒计时。功能各不相同,但打开任何一个页面,深色渐变背景、白色标题、圆角卡片、统一的返回按钮,视觉上一看就是"同一个应用"。

这种一致性不是巧合,而是刻意设计的结果。今天就从五个页面的共性出发,聊聊多页面应用的设计系统和架构思维。
完整效果
在这里插入图片描述

共性分析:五个页面都有的元素

打开任意两个页面对比,会发现它们有大量相同的结构:

元素 二维码 单位换算 随机决策 颜色提取 倒计时
渐变背景
返回按钮
页面标题
工具主色 #4F6EF7 #34C759 #FF6B35 #AF52DE #FF2D55
圆角卡片
深色背景色 #2A2A3E #2A2A3E #2A2A3E #2A2A3E #1E1E32

五个页面用了同一套设计语言,只是主色调不同。

渐变背景:统一的视觉基底

.linearGradient({
  direction: GradientDirection.Bottom,
  colors: [['#1A1A2E', 0.0], ['#16213E', 0.5], ['#0F3460', 1.0]]
})

在这里插入图片描述

五个页面的背景完全一样——从深蓝到更深蓝的三段渐变。这个渐变有三个作用:

  1. 统一感:所有页面共享同一个背景,切换时不会"跳"
  2. 深度感:渐变比纯色有层次,看起来更高级
  3. 衬托内容:深色背景让白色文字和彩色元素更醒目

为什么不每个页面用不同的渐变

用不同渐变会让每个页面更有"个性",但代价是失去统一性。用户从一个页面跳到另一个,视觉上会"断裂"。对于工具箱这种"多个工具共存"的应用,统一性比个性更重要。

导航栏:三种模式

五个页面的导航栏结构相似,但有细微差异:

模式一:纯返回 + 标题

Row() {
  Text('←').fontSize(22).fontColor('#FF6B35').onClick(() => router.back())
  Text('🎲 随机决策').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#FFFFFF').margin({left:12})
}.width('100%').padding({left:20,right:20,top:50,bottom:12})

在这里插入图片描述

随机决策、颜色提取、倒计时用这种模式——只有返回按钮和标题。

模式二:返回 + 标题 + 操作按钮

Row() {
  Text('←').fontSize(22).fontColor('#FF2D55').onClick(() => router.back())
  Text('⏳ 倒计时').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#FFFFFF').margin({left:12})
  Blank()
  Button('+ 新增').fontSize(13).height(34).borderRadius(10)
    .backgroundColor('#FF2D55').fontColor('#FFFFFF')
    .onClick(() => { this.showAdd = !this.showAdd; })
}.width('100%').padding({left:20,right:20,top:50,bottom:12})

在这里插入图片描述

倒计时页面在标题右边加了"+ 新增"按钮。Blank() 把按钮推到最右边。

模式三:返回 + 标题(居左对齐)

二维码和单位换算的标题在左边,和返回按钮同行。

为什么返回按钮的 color 不同

每个页面的返回按钮颜色和该工具的主色一致——二维码用蓝色(#4F6EF7),单位换算用绿色(#34C759),随机决策用橙色(#FF6B35)。这是"品牌色"在细节上的体现。

颜色系统:每个工具自己的主色

const TOOLS: ToolItem[] = [
  { name: '二维码生成', color: '#4F6EF7' },  // 蓝色
  { name: '单位换算', color: '#34C759' },    // 绿色
  { name: '随机决策', color: '#FF6B35' },    // 橙色
  { name: '颜色提取', color: '#AF52DE' },    // 紫色
  { name: '倒计时', color: '#FF2D55' },      // 红色
];

五种颜色的选择

五种颜色饱和度相近(都在 60-80% 之间),在深色背景上都能看清。但色相不同(蓝、绿、橙、紫、红),用户可以通过颜色快速识别工具。

颜色在页面中的应用

每个工具的颜色出现在三个地方:

  1. 首页卡片backgroundColor(item.color)
  2. 导航栏返回按钮.fontColor('#4F6EF7')
  3. 页面内的强调元素:按钮、滑块、进度条等

为什么不统一用一种颜色

统一用一种颜色会让页面更简洁,但用户在首页靠颜色区分工具。如果所有页面都是蓝色,用户打开后需要看标题才知道"这是哪个工具"。颜色是最直观的识别方式。

字号系统:四个层级

五个页面的字号高度一致:

层级 字号 粗细 用途
标题 18px Bold 页面标题、卡片名称
正文 14-16px Medium 输入框文字、列表项
辅助 11-12px Normal 描述文字、标签
强调 24-40px Bold/Lighter 结果数字、大标题

为什么强调数字用 Lighter 而不是 Bold

Text(this.result).fontSize(40).fontWeight(FontWeight.Lighter)

Lighter 是更细的字重。大号数字用细体比粗体更优雅——粗体大数字会显得笨重,细体更精致。

间距系统:20px 基准

五个页面的左右边距都是 20px:

.padding({left:20, right:20, top:50, bottom:...})

为什么用 20px

20px 是移动端常见的边距值——太小(8px)会显得拥挤,太大(40px)会浪费空间。20px 在大多数屏幕上都能保持良好的可读性。

top: 50 的原因

导航栏的 top padding 是 50px,留出状态栏的空间。如果不用 50px,标题会和状态栏重叠。

卡片样式:圆角和阴影

.borderRadius(16)
.shadow({radius: 8, color: '#00000022', offsetY: 4})
.backgroundColor('#1E1E32')

圆角 16px

五个页面的卡片圆角都是 16px(或 18px)。大圆角让卡片更柔和,符合现代 UI 趋势。

阴影的统一

阴影的参数略有不同(radius 8-12,color 22%-44% 透明度),但整体风格一致——深色阴影,向下偏移。

背景色的微调

大部分页面用 #2A2A3E,倒计时用 #1E1E32。略有差异,但都在深色范围内,视觉上不会冲突。

路由架构:push + back

import { router } from '@kit.ArkUI';

// 首页跳转
navTo(page: string): void {
  router.pushUrl({ url: page });
}

// 子页面返回
Text('←').onClick(() => router.back())

为什么用 push 而不是 replace

pushUrl 把目标页面压入栈顶,用户按返回键能回到首页。如果用 replaceUrl,首页会被替换掉,用户按返回键直接退出应用。

页面栈的管理

五个工具页面都用 pushUrl 进入,用 back 返回。页面栈结构:

首页 → 工具页面 → (用户按返回)→ 首页

简单清晰,不需要额外管理。

不一致性:可以改进的地方

五个页面虽然整体一致,但有一些细微差异:

1. 背景色不完全统一

  • 二维码、单位换算、随机决策:卡片 #2A2A3E
  • 颜色提取:无卡片
  • 倒计时:卡片 #1E1E32

2. 阴影参数不完全统一

  • 二维码:shadow({radius:12, color: this.hex+'66'})
  • 单位换算:无阴影
  • 随机决策:shadow({radius:8, color:'#FF6B3522'})

3. 标题的 emoji 不统一

  • 二维码:📱
  • 单位换算:📐
  • 随机决策:🎲
  • 颜色提取:🎨
  • 倒计时:

emoji 本身没问题,但如果要更统一,可以不用 emoji,纯文字标题。

4. 返回按钮的大小

五个页面的返回按钮都是 fontSize(22),但颜色不同。如果要更统一,可以固定一个颜色(比如白色)。

设计系统的提取

如果要让五个页面更一致,可以提取一个设计系统:

// theme/CommonTheme.ts
export const THEME = {
  // 渐变背景
  gradient: {
    direction: GradientDirection.Bottom,
    colors: [['#1A1A2E', 0.0], ['#16213E', 0.5], ['#0F3460', 1.0]]
  },
  // 字号
  fontSize: {
    title: 18,
    body: 15,
    caption: 12,
    result: 40
  },
  // 间距
  spacing: {
    page: 20,
    navTop: 50,
    navBottom: 12
  },
  // 卡片
  card: {
    radius: 16,
    bgColor: '#1E1E32',
    shadow: { radius: 8, color: '#00000022', offsetY: 4 }
  }
};

在这里插入图片描述

然后每个页面引用 THEME 而不是硬编码值:

.linearGradient(THEME.gradient)
.padding({left: THEME.spacing.page, right: THEME.spacing.page})

好处

修改一个地方,所有页面同步更新。比如要把渐变背景改成从上到下,只需要改 THEME.gradient,不需要改五个文件。

坏处

增加了间接层,代码可读性降低。对于只有五个页面的小应用,直接硬编码可能更简单。

踩坑记录

坑 1:渐变背景的层级

渐变背景加在最外层 Column 上。如果加在内层 Column 上,滚动时背景不会跟着动。

坑 2:导航栏的 top padding

不同设备的状态栏高度不同。固定 50px 在大部分设备上没问题,但在某些设备上可能不够。可以用 env(statusbar_height) 动态获取。

坑 3:router.back() 的行为

router.back() 返回上一页。如果页面栈为空(比如直接进入工具页面),back() 会退出应用。需要确保从首页进入工具页面。

坑 4:ForEach 的 key

五个页面的 ForEach 都没有显式指定 key。对于静态列表没问题,但如果列表会动态增删,需要指定 key 避免渲染错误。

坑 5:颜色的可访问性

白色文字(#FFFFFF)在深色背景上对比度足够,但灰色文字(#666666)可能在某些屏幕上不够清晰。可以用 WebAIM 对比度检查工具验证。

代码改进建议

1. 提取公共组件

把导航栏、卡片、按钮等公共组件提取成独立文件,五个页面引用。

2. 统一阴影参数

把阴影参数统一成一个常量,避免每个页面自己写。

3. 统一背景色

把卡片背景色统一成一个值,减少视觉差异。

4. 加载动画

页面切换时可以加过渡动画,让跳转更流畅。

5. 深色模式适配

当前固定深色主题。如果要支持浅色模式,需要把颜色值提取成变量。

总结

小工具百宝箱的五个页面共享一套设计语言——深色渐变背景、20px 边距、18px 粗体标题、16px 圆角卡片、每个工具自己的主色。这种一致性让用户在切换工具时不会"迷失"。

适用边界:这个部分适合用作多页面应用设计一致性的学习案例,涵盖了设计系统提取、颜色系统、字号层级、间距系统、路由架构等核心知识点。但如果要上架应用商店,还需要补充公共组件提取、统一阴影/背景色、加载动画、深色模式适配等内容。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐