适用范围

本文适用于使用 ArkTS 和 ArkUI 开发的 HarmonyOS 应用,说明如何将 .ttf.otf 字体文件放入工程、完成字体注册,并在 Text 等组件中使用

较早的项目可能使用 @ohos.font 中的静态 registerFont() 方法,该方法在较新的 API 中已经废弃,新代码应优先使用 UIContext 提供的字体管理接口

准备字体文件

第三方字体通常以 .ttf.otf 文件提供,HarmonyOS 工程可以同时存放多个字体文件

使用字体前需要确认以下事项

  • 字体授权允许嵌入应用并随安装包分发
  • 中文字体文件通常较大,需要关注 HAP 安装包体积
  • 文件名建议只使用英文字母、数字、连字符和下划线

放置字体文件

在模块的 resources/rawfile 目录下创建 fonts 目录,并将字体文件放入其中

entry/src/main/resources/rawfile/fonts/SourceHanSerifSC-Regular.otf

字体授权文件 ( license / OFL ) 建议与字体一起保留,但授权文件不参与字体注册

定义字体名称常量

建议将应用使用的字体名称集中定义,避免在多个页面中重复填写字符串

在以下位置创建字体配置文件

entry/src/main/ets/common/AppFonts.ets

写入

export const APP_SERIF_FONT_FAMILY: string = 'xxSourceHanSerif';

这里的 xxSourceHanSerif 是应用内部使用的字体别名,可以自行命名

该名称不必与字体文件名完全一致,但注册字体和使用字体时必须保持一致

注册字体

字体文件放入工程后不能直接通过 .fontFamily() 使用,必须先在 UI 上下文中完成注册

可以在应用入口页面的 aboutToAppear() 生命周期中注册,例如

import { hilog } from '@kit.PerformanceAnalysisKit';
import { APP_SERIF_FONT_FAMILY } from '../common/AppFonts';

@Entry
@Component
struct Index {
  aboutToAppear(): void {
    try {
      this.getUIContext().getFont().registerFont({
        familyName: APP_SERIF_FONT_FAMILY,
        familySrc: $rawfile('fonts/SourceHanSerifSC-Regular.otf')
      });
    } catch (error) {
      hilog.error(
        0x0000,
        'HomePage',
        'Register app font failed: %{public}s',
        JSON.stringify(error)
      );
    }
  }

  build() {
    Column() {
      Text('应用首页')
    }
  }
}

familyName

字体在应用中的注册名称,后续 .fontFamily() 必须使用同一个名称

familySrc

字体文件资源,使用 $rawfile() 进行链接

$rawfile('fonts/SourceHanSerifSC-Regular.otf')

注册时机

应在首次渲染使用该字体的组件之前完成注册

单 UIAbility、单主窗口应用通常可以在入口页面注册一次,不应在每个普通组件中重复注册

如果应用包含多个 UIAbility、多个窗口或彼此独立的 UIContext,需要在相应 UIContext 中分别确认字体已经注册

在组件中使用字体

先导入字体名称常量

import { APP_SERIF_FONT_FAMILY } from '../common/AppFonts';

然后通过 .fontFamily() 应用字体

Text('瓷序')
  .fontSize(30)
  .fontFamily(APP_SERIF_FONT_FAMILY)
  .fontColor('#D8A756')

只需要对部分文字使用第三方字体时,给对应的 Text 组件设置 .fontFamily() 即可

Column({ space: 12 }) {
  Text('使用第三方字体的标题')
    .fontFamily(APP_SERIF_FONT_FAMILY)
    .fontSize(28)

  Text('继续使用系统默认字体的正文')
    .fontSize(16)
}

注册多个字体文件

fonts 目录中可以放置多个 .otf.ttf 文件,每个需要使用的字体文件都应单独注册

例如

entry/src/main/resources/rawfile/fonts/
├─ SourceHanSerifSC-Regular.otf
├─ SourceHanSerifSC-Medium.otf
└─ SourceHanSansSC-Regular.otf

可以先定义多个字体名称

export const APP_SERIF_REGULAR: string = 'xxSerifRegular';
export const APP_SERIF_MEDIUM: string = 'xxSerifMedium';
export const APP_SANS_REGULAR: string = 'xxSansRegular';

再分别注册

const fontManager = this.getUIContext().getFont();

fontManager.registerFont({
  familyName: APP_SERIF_REGULAR,
  familySrc: $rawfile('fonts/SourceHanSerifSC-Regular.otf')
});

fontManager.registerFont({
  familyName: APP_SERIF_MEDIUM,
  familySrc: $rawfile('fonts/SourceHanSerifSC-Medium.otf')
});

fontManager.registerFont({
  familyName: APP_SANS_REGULAR,
  familySrc: $rawfile('fonts/SourceHanSansSC-Regular.otf')
});

使用时选择对应的字体名称

Text('中等字重标题')
  .fontFamily(APP_SERIF_MEDIUM)
  .fontSize(24)

Text('无衬线正文')
  .fontFamily(APP_SANS_REGULAR)
  .fontSize(16)

推荐的工程组织方式

字体文件、字体名称和字体使用代码建议分别承担不同职责

entry/src/main/resources/rawfile/fonts/

存放字体文件和授权文件

entry/src/main/ets/common/AppFonts.ets

定义字体名称常量

entry/src/main/ets/pages/Index.ets

在入口页面注册字体

entry/src/main/ets/components/
entry/src/main/ets/pages/

在具体组件和页面中通过 .fontFamily() 使用字体

完整链接关系

字体从文件到界面生效的关系如下

字体文件
entry/src/main/resources/rawfile/fonts/SourceHanSerifSC-Regular.otf
        │
        │ $rawfile('fonts/SourceHanSerifSC-Regular.otf')
        ▼
registerFont({ familyName, familySrc })
        │
        │ familyName: 'xxSourceHanSerif'
        ▼
APP_SERIF_FONT_FAMILY
        │
        │ .fontFamily(APP_SERIF_FONT_FAMILY)
        ▼
Text 等 ArkUI 组件

常见问题

粗体效果不符合预期

不要只依赖系统模拟粗体,将对应的 Medium、Semibold 或 Bold 字体文件单独注册并使用

应用安装包明显变大

中文字体可能包含大量字符,应只保留项目确实需要的字体和字重,并在字体授权允许的前提下考虑使用官方子集版本

字体文件可以放多个吗

可以,同一个 fonts 目录能够存放多个 .otf.ttf 文件,但每个实际使用的文件都需要注册

Logo

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

更多推荐