引言

在移动应用界面设计中,字体是用户体验的第一触点。不同于 Web 前端的 CSS @font-face 即可加载网络字体,也不同于 iOS 的有限系统字体集,HarmonyOS NEXT 的 @ohos.font 模块提供了一套完整的字体管理 API——开发者可以枚举系统中安装的所有字体、查询任意字体的详细元数据(包括 weight、italic、monoSpace 等)、注册自定义 .ttf/.otf 文件供全局使用,甚至窥探系统 UI 字体配置的内部结构。

本文构建一个字体实验室 Demo,浏览系统字体列表并让每种字体以自身字形展示其名称,点击即可查看该字体的完整元数据(family/subfamily/postScriptName/weight/width/italic/monoSpace/symbolic),在实时预览区输入任意文字以选中的字体渲染,并演示通过 registerFont() 动态加载自定义 .ttf 文件。

读完本文,你将掌握:

  • 字体枚举getSystemFontList() 返回系统安装的所有字体名数组
  • 字体详情查询getFontByName() 返回 FontInfo — 9 个字段的完整字体档案
  • 字形预览:通过 fontFamily() 属性将字体名作用于 Text 组件
  • 自定义字体注册registerFont({ familyName, familySrc }) 动态加载外部字体文件
  • UI 字体配置getUIFontConfig() 暴露系统的 generic/alias/adjust/fallback 字体策略
  • API 演进:部分 API 在 API 18 标记 deprecated,迁移到 UIContext.Font 的趋势

环境与权限

@ohos.font 属于 ArkUI 工具包,自 API 9 开始提供。导入方式:

import font from '@ohos.font';

零权限需求:字体查询和注册操作完全是客户端的行为,不涉及系统服务调用或用户数据访问,因此不需要任何权限声明

一、核心数据类型

1.1 FontInfo — 字体元数据档案

interface FontInfo {
  path: string;              // 字体文件路径
  postScriptName: string;    // PostScript 名称(字体唯一标识)
  fullName: string;          // 完整字体名
  family: string;            // 字体系列名
  subfamily: string;         // 子系列名(如 Bold/Italic/Regular)
  weight: number;            // 字重(100=Thin ~ 900=Black)
  width: number;             // 字体宽度
  italic: boolean;           // 是否斜体
  monoSpace: boolean;        // 是否等宽字体
  symbolic: boolean;         // 是否支持符号字体
}

FontInfo 是最核心的数据结构——它完整描述了一个字体的"身份档案"。

  • postScriptName 是字体的"身份证号",每个字体文件有且只有一个
  • family + subfamily 共同定位字体在族系中的位置
  • weight 遵循 CSS 字重规范,100(Thin)到 900(Black)
  • italic 标识是否斜体变体;monoSpace 标识是否等宽;symbolic 标识是否包含符号字形

1.2 FontOptions — 注册配置

interface FontOptions {
  familyName: string | Resource;   // 注册后的字体名
  familySrc: string | Resource;    // 字体文件路径
}

familyName 是注册后用于 Text().fontFamily() 的名称;familySrc 指向 .ttf 或 .otf 文件的沙箱路径。

1.3 UIFontConfig — 系统字体策略

interface UIFontConfig {
  fontDir: Array<string>;                    // 系统字体文件目录
  generic: Array<UIFontGenericInfo>;         // 通用字体组配置
  fallbackGroups: Array<UIFontFallbackGroupInfo>;  // 回退字体策略
}

UIFontConfig 是 HarmonyOS 字体系统的"配置档案",暴露了系统如何组织通用字体(generic)和回退字体(fallback)的策略。这是理解 HarmonyOS 多语言排版能力的关键入口。

二、枚举系统字体列表

2.1 getSystemFontList()

let fontNames: string[] = font.getSystemFontList();

同步返回所有系统安装字体的名称数组。典型系统包含 50-100 款字体,涵盖中英文、日文、韩文等多个语言族系。

2.2 以字体本身展示字体名

最基本的"字体预览"就是把字体作用在自身名称上:

ForEach(fontNames, (name: string) => {
  Text(name)
    .fontFamily(name)   // 精确匹配——该字体渲染自己的名字
    .fontSize(16)
})

这个简单的技巧让用户能在列表中直观感受到每个字体的笔画风格。HarmonyOS Sans 系列字体会展示为现代无衬线风格,而宋体/楷体等中文字体会呈现出各自的经典造型。
在这里插入图片描述
在这里插入图片描述

三、查询字体详情

3.1 getFontByName()

let info: font.FontInfo = font.getFontByName('HarmonyOS Sans SC');

同步返回指定字体名的完整 FontInfo 对象。如果字体名不存在,该方法会抛出异常(需要 try/catch 包裹)。

3.2 字重解码

weight 字段的值与字重名称的对应关系:

Weight 值 名称 CSS 等价
100 Thin font-weight: 100
200 ExtraLight font-weight: 200
300 Light font-weight: 300
400 Regular / Normal font-weight: 400
500 Medium font-weight: 500
600 SemiBold font-weight: 600
700 Bold font-weight: 700
800 ExtraBold font-weight: 800
900 Black font-weight: 900

在 Demo 中,我们通过 weightLabel() 辅助函数将数值映射为人类可读的字重名称。

3.3 实战代码:获取并展示字体详情

let name = 'HarmonyOS Sans SC';
let info = font.getFontByName(name);

console.log('字体全名: ' + info.fullName);
console.log('PostScript 标识: ' + info.postScriptName);
console.log('字重: ' + info.weight + ' (Regular)');
console.log('是否等宽: ' + (info.monoSpace ? '是' : '否'));
console.log('是否斜体: ' + (info.italic ? '是' : '否'));
console.log('是否支持符号: ' + (info.symbolic ? '是' : '否'));
console.log('文件路径: ' + info.path);

四、自定义字体注册

4.1 registerFont()

try {
  font.registerFont({
    familyName: 'MyBrandFont',
    familySrc: '/data/storage/el2/base/files/fonts/brand.ttf'
  });
  console.log('自定义字体注册成功');
} catch (e) {
  console.error('注册失败: ' + JSON.stringify(e));
}

registerFont() 将外部 .ttf/.otf 字体文件加载到系统 FontManager 中。注册成功后,该字体可以通过 fontFamily('MyBrandFont') 在任何 Text 组件中使用,效果等同于系统自带字体。

注意事项

  • familySrc 路径必须是应用沙箱内的绝对路径(如 /data/storage/el2/base/...
  • 字体文件需要提前放入应用的沙箱存储中(通常通过 file.fs 写入)
  • 注册是进程级的——应用退出后需要重新注册
  • 该方法在 API 18 标记为 deprecated,推荐迁移到 UIContext.Font#registerFont

4.2 注册后验证

// 注册后立即验证
let names = font.getSystemFontList();
if (names.indexOf('MyBrandFont') >= 0) {
  console.log('字体已在系统列表中');
}

注册成功后,getSystemFontList() 的返回数组中会包含新注册的字体名。

五、系统 UI 字体配置

5.1 getUIFontConfig()

let config = font.getUIFontConfig();

console.log('字体目录: ' + config.fontDir.length + ' 个');
config.fontDir.forEach((dir, idx) => {
  console.log('  [' + idx + '] ' + dir);
});

console.log('通用字体组: ' + config.generic.length + ' 组');
config.generic.forEach((gen) => {
  console.log('  ' + gen.family + ' (别名: ' + gen.alias.length + ')');
});

console.log('回退字体组: ' + config.fallbackGroups.length + ' 组');

getUIFontConfig() 返回的是 HarmonyOS 字体系统的完整内部策略配置,包含三个核心维度:

  1. fontDir:系统从哪些目录加载字体文件(通常是 /system/fonts 等系统路径)
  2. generic:通用字体组——每组的 family 定义了一个抽象字体系列(如 “sans-serif”),alias 定义了不同字重的实际映射字体,adjust 定义了字重映射规则
  3. fallbackGroups:回退策略——当渲染指定字体缺失的字形时,按 language + family 匹配回退字体

这个 API 对于想深入理解 HarmonyOS 文本渲染管线的开发者来说是无价的。

六、Text.fontFamily() — 在 UI 中使用字体

获取字体名和详情的最终目的是在 UI 渲染中使用它们:

// 使用系统字体
Text('HarmonyOS 鸿蒙操作系统')
  .fontFamily('HarmonyOS Sans SC')
  .fontSize(28)

// 使用自定义注册字体
Text('Welcome to HarmonyOS')
  .fontFamily('MyBrandFont')
  .fontSize(24)
  .fontWeight(FontWeight.Bold)

fontFamily() 属性接受字体名(family name)字符串。系统会优先使用指定字体渲染文本;如果该字体缺少某个字符的字形,会自动触发回退机制(根据 UIFontConfig.fallbackGroups 查找替代字体)。

七、API 演进趋势

从 API 版本注解中可以看出字体 API 的演进方向:

API 状态 新方向
font.registerFont() API 18 deprecated UIContext.Font#registerFont
font.getSystemFontList() API 18 deprecated UIContext.Font#getSystemFontList
font.getFontByName() API 18 deprecated UIContext.Font#getFontByName

HarmonyOS 正在将字体管理从全局单例模型迁移到 UIContext 上下文模型。这意味着未来的字体操作将按 UIWindow/UIAbility 上下文隔离——不同的 Ability 实例可以有不同的字体配置,而不共享全局状态。这对于多窗口应用、跨设备分布式场景来说是一个重要的架构升级。

八、实战 Demo:字体实验室

页面结构

字体实验室
├── 状态栏 — 已加载字体数量 + UIFontConfig 摘要
├── 字体预览区
│   ├── 可编辑样本文字输入框
│   ├── 字号调节(± 按钮,12-72px)
│   └── 大尺寸预览卡片(以选中字体渲染样本文字)
├── 字体详情面板(选中字体后显示)
│   ├── fullName + postScriptName
│   ├── family / subfamily / weight
│   ├── italic / monoSpace / symbolic 标签
│   └── 字体文件路径
├── 系统字体列表(50+ 款)
│   ├── 每种字体以自身字形展示其名称
│   ├── 字重标签(Thin/Regular/Bold 等)
│   └── 高亮选中项
├── 自定义字体注册
│   ├── 字体名 + 文件路径输入
│   └── 注册按钮 + 状态反馈
└── 核心 API 参考 — 10 个关键 API

4 个交互点

  1. 浏览系统字体列表 — 每种字体以自身字形展示其名称,右侧显示字重标签,点击选中高亮
  2. 实时字形预览 — 在顶部输入框编辑任意文字,选择字号(12-72),选中字体实时渲染用户输入的样本文字
  3. 字体详情查看 — 选中字体后展示完整的 FontInfo(9 个字段),含 family/subfamily/weight/italic/monoSpace/symbolic 标签
  4. 自定义字体注册 — 输入字体名和沙箱路径,点击"注册字体"将外部 .ttf 文件注册到系统,成功后刷新字体列表

核心代码位置

完整代码在 dev/entry/src/main/ets/pages/TypographyLabPage.ets(约 330 行),路由已注册为 pages/TypographyLabPage

九、与 CSS @font-face 的对比

对于有 Web 开发经验的开发者:

维度 CSS @font-face HarmonyOS @ohos.font
字体注册 @font-face { font-family; src; } font.registerFont()
字体枚举 无标准 API font.getSystemFontList()
字体元数据 无标准 API font.getFontByName() — FontInfo
字体策略查询 font.getUIFontConfig()
字形变体 font-weight / font-style FontInfo.weight / .italic
回退机制 font-family: A, B, C UIFontConfig.fallbackGroups
运行时动态加载 Web Font Loader 库 font.registerFont() 原生支持

HarmonyOS 的字体 API 远超 CSS 标准的能力范围——不仅提供了运行时注册,还提供了完整的字体元数据查询和系统策略检查。

十、总结

@ohos.font 是 HarmonyOS NEXT 字体系统的程序化入口,核心能力:

  1. 字体枚举getSystemFontList() 返回系统全部字体名,通过 fontFamily() 即时预览
  2. 元数据查询getFontByName() 提供 9 字段 FontInfo,覆盖字重/宽度/斜体/等宽/符号等所有维度
  3. 自定义字体registerFont() 支持运行时加载外部字体文件,品牌定制化不再受限
  4. 策略洞察getUIFontConfig() 暴露系统通用字体和回退策略的内部配置
  5. 演进趋势:API 18 起迁移到 UIContext 上下文模型,为多窗口场景铺路

结合 SymbolGlyph(系统图标)、RichEditor(富文本编辑器)和 Span(富文本排版),HarmonyOS 开发者已经掌握了从字体管理到排版渲染的完整工具链。


Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐