鸿蒙开发-想加载自定义字体?Typeface字体管理详解
本文介绍了HarmonyOS中Typeface类的使用方法,主要包括:1) Typeface代表字体设计风格,与Font类配合使用;2) 获取字体族名的getFamilyName方法;3) 从系统文件加载字体的makeFromFile方法;4) 从应用rawfile目录加载字体的makeFromRawFile方法;5) API 20新增的支持字体属性的makeFromFileWithArgumen
想用自定义字体?Typeface 让你轻松管理字体文件
你有没有想过在 APP 里使用一种特别的字体?比如用一种手写体来显示标题,或者用一种等宽字体来显示代码?在 HarmonyOS 的 drawing 模块里,Typeface 类就是专门用来管理字体的。
Typeface 是什么?
下面是 Typeface 字体加载的各种方式:
简单说,Typeface 就代表一种"字体"。我们平时说的"宋体"、“楷体”、“黑体”,在代码里就是不同的 Typeface 对象。每个 Typeface 对象对应一种字体设计,包含了该字体的所有字形信息。
Typeface 和 Font 的关系是:Font 是"字型",控制文字的大小、粗细、倾斜等属性;Typeface 是"字体",决定文字用哪种设计风格。你可以把 Typeface 理解为"字体文件",Font 理解为"字体设置"。
获取字体族名:getFamilyName
每个字体都有一个"族名",就是这套字体设计的名称。你可以用 getFamilyName 来获取:
import { drawing } from '@kit.ArkGraphics2D';
const font = new drawing.Font();
let typeface = font.getTypeface();
let familyName = typeface.getFamilyName();
这段代码先从 Font 对象获取关联的 Typeface,然后获取它的族名。族名通常是一个有意义的字符串,比如 “HarmonyOS Sans”、“Roboto” 等。
从字体文件加载:makeFromFile
如果你想使用系统里的某个字体文件,用 makeFromFile:
import { RenderNode } from '@kit.ArkUI';
import { drawing } from '@kit.ArkGraphics2D';
class TextRenderNode extends RenderNode {
async draw(context: DrawContext) {
const canvas = context.canvas;
let font = new drawing.Font();
let str = "/system/fonts/HarmonyOS_Sans_Italic.ttf";
const mytypeface = drawing.Typeface.makeFromFile(str);
font.setTypeface(mytypeface);
const textBlob = drawing.TextBlob.makeFromString("Hello World", font, drawing.TextEncoding.TEXT_ENCODING_UTF8);
canvas.drawTextBlob(textBlob, 60, 100);
}
}
这里我们加载了系统自带的斜体字体文件 HarmonyOS_Sans_Italic.ttf,然后用 font.setTypeface 把它设置到 Font 上。之后用这个 Font 绘制的文字就会使用斜体样式。
makeFromFile 的参数是字体文件的路径。你可以用系统字体路径(如 /system/fonts/),也可以用应用沙箱路径。
从 rawfile 加载:makeFromRawFile
如果你把字体文件打包在应用的 rawfile 目录下,可以用 makeFromRawFile 来加载:
import { RenderNode } from '@kit.ArkUI';
import { drawing } from '@kit.ArkGraphics2D';
class TextRenderNode extends RenderNode {
async draw(context: DrawContext) {
const canvas = context.canvas;
let font = new drawing.Font();
const myTypeFace = drawing.Typeface.makeFromRawFile($rawfile('HarmonyOS_Sans_Bold.ttf'));
font.setTypeface(myTypeFace);
const textBlob = drawing.TextBlob.makeFromString("Hello World", font, drawing.TextEncoding.TEXT_ENCODING_UTF8);
canvas.drawTextBlob(textBlob, 60, 100);
}
}
$rawfile('HarmonyOS_Sans_Bold.ttf') 引用的是 resources/rawfile/HarmonyOS_Sans_Bold.ttf 文件。你也可以放在子目录里,比如 $rawfile('ttf/HarmonyOS_Sans_Bold.ttf')。
这种方式的好处是字体文件会随应用一起打包,不依赖系统字体。
带字体属性加载:makeFromFileWithArguments / makeFromRawFileWithArguments
从 API version 20 开始,你可以在加载字体的时候就指定字体属性:
import { RenderNode } from '@kit.ArkUI';
import { drawing } from '@kit.ArkGraphics2D';
class TextRenderNode extends RenderNode {
async draw(context: DrawContext) {
const canvas = context.canvas;
let font = new drawing.Font();
let str = "/system/fonts/HarmonyOS_Sans_Italic.ttf";
let typeFaceArgument = new drawing.TypefaceArguments();
const myTypeFace = drawing.Typeface.makeFromFileWithArguments(str, typeFaceArgument);
font.setTypeface(myTypeFace);
const textBlob = drawing.TextBlob.makeFromString("Hello World", font, drawing.TextEncoding.TEXT_ENCODING_UTF8);
canvas.drawTextBlob(textBlob, 60, 100);
}
}
import { RenderNode } from '@kit.ArkUI';
import { drawing } from '@kit.ArkGraphics2D';
class TextRenderNode extends RenderNode {
async draw(context: DrawContext) {
const canvas = context.canvas;
let font = new drawing.Font();
let typeFaceArgument = new drawing.TypefaceArguments();
const myTypeFace = drawing.Typeface.makeFromRawFileWithArguments($rawfile('HarmonyOS_Sans_Bold.ttf'), typeFaceArgument);
font.setTypeface(myTypeFace);
const textBlob = drawing.TextBlob.makeFromString("Hello World", font, drawing.TextEncoding.TEXT_ENCODING_UTF8);
canvas.drawTextBlob(textBlob, 60, 100);
}
}
TypefaceArguments 可以让你指定字体的变体参数(比如字重),具体用法我们在下一篇文章里会详细讲。
基于当前字体创建变体:makeFromCurrent
如果你已经有一个 Typeface 对象,想基于它创建一个变体(比如改变字重),可以用 makeFromCurrent:
import { RenderNode } from '@kit.ArkUI';
import { drawing } from '@kit.ArkGraphics2D';
class TextRenderNode extends RenderNode {
async draw(context: DrawContext) {
const canvas = context.canvas;
let typeArguments = new drawing.TypefaceArguments();
typeArguments.addVariation("wght", 100);
const myTypeFace = drawing.Typeface.makeFromFile("/system/fonts/HarmonyOS_Sans_SC.ttf");
const typeFace1 = myTypeFace.makeFromCurrent(typeArguments);
let font = new drawing.Font();
font.setTypeface(typeFace1);
const textBlob = drawing.TextBlob.makeFromString("Hello World", font, drawing.TextEncoding.TEXT_ENCODING_UTF8);
canvas.drawTextBlob(textBlob, 60, 100);
}
}
这段代码先加载了 HarmonyOS_Sans_SC.ttf,然后基于它创建了一个字重为 100(非常细)的变体。TypefaceArguments 的具体用法我们在下一篇文章里会详细讲。
检查字体属性:isBold / isItalic
从 API version 23 开始,你可以检查一个 Typeface 是否是粗体或斜体:
import { drawing } from '@kit.ArkGraphics2D';
const font = new drawing.Font();
let typeface = font.getTypeface();
let isBold = typeface.isBold();
let isItalic = typeface.isItalic();
这两个方法在需要根据字体样式做不同处理时很有用。比如你可能想根据当前字体是否是粗体来决定是否需要额外加粗。
实际应用场景
下面是多语言字体选择的典型流程:
场景一:使用自定义品牌字体
很多 APP 都有自己的品牌字体。你可以把字体文件放在 rawfile 目录下,然后用 Typeface 加载:
let brandFont = drawing.Typeface.makeFromRawFile($rawfile('MyBrandFont.ttf'));
let font = new drawing.Font();
font.setTypeface(brandFont);
font.setSize(24);
// 用这个 font 绘制品牌文字
场景二:代码高亮显示
做代码编辑器或代码显示功能时,通常需要等宽字体:
let codeFont = drawing.Typeface.makeFromFile("/system/fonts/monospace.ttf");
let font = new drawing.Font();
font.setTypeface(codeFont);
font.setSize(14);
// 用这个 font 显示代码
场景三:多语言支持
不同语言可能需要不同的字体。比如中文用一种字体,英文用另一种:
let chineseFont = drawing.Typeface.makeFromFile("/system/fonts/HarmonyOS_Sans_SC.ttf");
let englishFont = drawing.Typeface.makeFromFile("/system/fonts/HarmonyOS_Sans.ttf");
// 根据文本内容选择字体
function getFontForText(text: string): drawing.Font {
let font = new drawing.Font();
if (/[\u4e00-\u9fa5]/.test(text)) {
font.setTypeface(chineseFont);
} else {
font.setTypeface(englishFont);
}
font.setSize(20);
return font;
}
场景四:字体变体切换
同一个字体族可能有多种变体(细体、常规、粗体等),用 Typeface 可以方便地切换:
let regularTypeface = drawing.Typeface.makeFromFile("/system/fonts/HarmonyOS_Sans_Regular.ttf");
let boldTypeface = drawing.Typeface.makeFromFile("/system/fonts/HarmonyOS_Sans_Bold.ttf");
let italicTypeface = drawing.Typeface.makeFromFile("/system/fonts/HarmonyOS_Sans_Italic.ttf");
// 根据需要选择不同的变体
注意事项
-
API 版本:Typeface 基础方法从 API version 11 开始支持,
makeFromFile从 12 开始,makeFromRawFile从 18 开始,带 Arguments 的方法从 20 开始,isBold/isItalic从 23 开始。 -
物理像素:和其他 drawing 对象一样,使用物理像素单位。
-
线程安全:单线程模型,需要自己管理线程安全。
-
字体文件路径:确保字体文件路径正确,文件存在且可读。如果文件不存在,
makeFromFile可能会返回空指针。 -
性能考虑:加载字体文件是一个相对耗时的操作,建议把常用的 Typeface 对象缓存起来重复使用,而不是每次需要时都重新加载。
小结
Typeface 是 drawing 模块里管理字体的核心类。它让你能够:
- 从系统字体或 rawfile 加载自定义字体
- 获取字体的族名
- 基于现有字体创建变体
- 检查字体是否是粗体或斜体
在实际开发中,Typeface 通常和 Font 配合使用——Typeface 决定"用什么字体",Font 决定"怎么显示"。掌握了 Typeface,你就能在 APP 里使用任何你喜欢的字体了。
更多推荐


所有评论(0)