• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 自定义字体的注册和使用(ArkTS)
2
3## 场景介绍
4
5自定义字体是指开发者根据应用需求创建或选择的字体,通常用于实现特定的文字风格或满足独特的设计要求。当应用需要使用特定的文本样式和字符集时,可以注册并使用自定义字体进行文本渲染。
6
7## 实现流程
8
9**自定义字体的注册**是指将字体文件(如ttf、otf文件等)从应用资源注册到系统中,使得应用能够使用这些字体进行文本渲染。注册过程通常指将字体文件通过字体管理接口注册到系统字体库中,以便在应用中进行调用。
10
11**自定义字体的使用**是指在应用中显式指定使用已注册的自定义字体进行文本渲染。开发者可以根据需要选择特定的文本样式(如常规、粗体、斜体等),并将其应用到UI元素、文本控件或其他文本展示区域,以确保符合设计要求并提供一致的视觉效果。
12
13
14## 接口说明
15
16自定义字体注册和使用的常用接口如下表所示,详细接口说明请见[@ohos.graphics.text (文本模块)](../reference/apis-arkgraphics2d/js-apis-graphics-text.md)。
17
18| 接口 | 描述 |
19| -------- | -------- |
20| loadFontSync(name: string, path: string \| Resource): void | 同步接口,将路径对应的文件,以name作为使用的别名,注册自定义字体。<br/>**说明:**<br/>需保证使用自定义字体时,自定义字体已完成注册,非性能严格要求场景下,建议使用同步接口。 |
21| loadFont(name: string, path: string \| Resource): Promise&lt;void&gt; | 使用指定的别名和文件路径注册对应字体,使用Promise异步回调。此接口从API version 14开始支持。 |
22
23## 开发步骤
24
251. 导入依赖的相关模块。
26
27   ```ts
28   import { NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI'
29   import { UIContext } from '@kit.ArkUI'
30   import { text } from '@kit.ArkGraphics2D'
31   ```
32
332. 注册自定义字体。有以下两种方式:
34
35   ```ts
36   // 注册自定义字体
37   let fontCollection = text.FontCollection.getGlobalInstance()
38   // 方式一:/system/fonts/myFontFile.ttf文件仅为示例路径,应用根据自身实际填写文件路径
39   fontCollection.loadFontSync('myFamilyName0', 'file:///system/fonts/myFontFile.ttf')
40
41   // 方式二:确保已经将自定义字体myFontFile.ttf文件放在本应用工程的entry/src/main/resources/rawfile目录
42   fontCollection.loadFontSync('myFamilyName1',$rawfile('myFontFile.ttf'))
43   ```
44
453. 使用自定义字体。
46
47   ```ts
48   // 填写注册自定义字体时传入的字体家族名
49   let myFontFamily: Array<string> = ["myFamilyName0"]
50   // 设置文本样式
51   let myTextStyle: text.TextStyle = {
52     color: { alpha: 255, red: 255, green: 0, blue: 0 },
53     fontSize: 100,
54     // 在文本样式中加入可使用的自定义字体
55     fontFamilies: myFontFamily
56   };
57   ```
58
594. 创建段落样式,并使用字体管理器实例构造段落生成器PargraphBuilder实例。
60
61   ```ts
62   // 创建一个段落样式对象,以设置排版风格
63   let myParagraphStyle: text.ParagraphStyle = {textStyle: myTextStyle}
64   // 创建一个段落生成器
65   let paragraphBuilder: text.ParagraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection);
66   ```
67
685. 生成段落。
69
70   ```ts
71   // 在段落生成器中设置文本样式
72   ParagraphGraphBuilder.pushStyle(myTextStyle);
73   // 在段落生成器中设置文本内容
74   ParagraphGraphBuilder.addText("测试自定义字体");
75   // 通过段落生成器生成段落
76   let paragraph = ParagraphGraphBuilder.build();
77   ```
78
79## 完整示例
80
81这里以使用自定义注册字体方式一为例绘制“Custom font test”文本,并提供如下完整示例。
82
83请保证自定义字体文件已放置到设备正确的路径下。
84
85```ts
86// Index.ets
87import { NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI'
88import { UIContext } from '@kit.ArkUI'
89import { text } from '@kit.ArkGraphics2D'
90class MyRenderNode extends RenderNode {
91  async draw(context: DrawContext) {
92    // 创建画布canvas对象
93    const canvas = context.canvas
94    // 获取全局字体集实例
95    let fontCollection = text.FontCollection.getGlobalInstance() //获取Arkui全局FC
96    // 注册自定义字体
97    fontCollection.loadFontSync('myFamilyName', 'file:///system/fonts/myFontFile .ttf')
98    // 使用自定义字体
99    let myFontFamily: Array<string> = ["myFamilyName"] // 如果已经注册自定义字体,填入自定义字体的字体家族名
100    // 设置文本样式
101    let myTextStyle: text.TextStyle = {
102      color: { alpha: 255, red: 255, green: 0, blue: 0 },
103      fontSize: 100,
104      // 在文本样式中加入可使用的自定义字体
105      fontFamilies: myFontFamily
106    };
107    // 创建一个段落样式对象,以设置排版风格
108    let myParagraphStyle: text.ParagraphStyle = {
109      textStyle: myTextStyle,
110      align: 3,
111      wordBreak:text.WordBreak.NORMAL
112    };
113    // 创建一个段落生成器
114    let ParagraphGraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection)
115    // 在段落生成器中设置文本样式
116    ParagraphGraphBuilder.pushStyle(myTextStyle);
117    // 在段落生成器中设置文本内容
118    ParagraphGraphBuilder.addText("Custom font test");
119    // 通过段落生成器生成段落
120    let paragraph = ParagraphGraphBuilder.build();
121    // 布局
122    paragraph.layoutSync(1000);
123    paragraph.paint(canvas, 0, 800);
124  }
125}
126// 创建一个MyRenderNode对象
127function getNewRenderNode() {
128  const textNodeTest = new MyRenderNode();
129  textNodeTest.frame = { x: 0, y: 0, width: 500, height: 500 }
130  textNodeTest.pivot = { x: 0.5, y: 0.5 }
131  textNodeTest.scale = { x: 1, y: 1 }
132  return textNodeTest;
133}
134const textNode = new MyRenderNode();
135// 定义newNode的像素格式
136textNode.frame = { x: 0, y: 0, width: 500, height: 500 }
137textNode.pivot = { x: 0.5, y: 0.5 }
138textNode.scale = { x: 1, y: 1 }
139class MyNodeController extends NodeController {
140  private rootNode: FrameNode | null = null;
141  makeNode(uiContext: UIContext): FrameNode {
142    this.rootNode = new FrameNode(uiContext)
143    if (this.rootNode == null) {
144      return this.rootNode
145    }
146    const renderNode = this.rootNode.getRenderNode()
147    if (renderNode != null) {
148      renderNode.frame = { x: 0, y: 0, width: 300, height: 50 }
149      renderNode.pivot = { x: 0, y: 0 }
150    }
151    return this.rootNode
152  }
153  addNode(node: RenderNode): void {
154    if (this.rootNode == null) {
155      return
156    }
157    const renderNode = this.rootNode.getRenderNode()
158    if (renderNode != null) {
159      renderNode.appendChild(node)
160    }
161  }
162  clearNodes(): void {
163    if (this.rootNode == null) {
164      return
165    }
166    const renderNode = this.rootNode.getRenderNode()
167    if (renderNode != null) {
168      renderNode.clearChildren()
169    }
170  }
171}
172
173@Entry
174@Component
175struct RenderTest {
176  private myNodeController: MyNodeController = new MyNodeController()
177  build() {
178    Column() {
179      Row() {
180        NodeContainer(this.myNodeController)
181          .height('100%')
182      }
183      .height('90%')
184      .backgroundColor(Color.White)
185      Row(){
186        Button("Draw Text")
187          .fontSize('16fp')
188          .fontWeight(500)
189          .margin({ bottom: 24, right: 12 })
190          .onClick(() => {
191            this.myNodeController.clearNodes()
192            this.myNodeController.addNode(getNewRenderNode())
193          })
194          .width('50%')
195          .height(40)
196          .shadow(ShadowStyle.OUTER_DEFAULT_LG)
197      }
198      .width('100%')
199      .justifyContent(FlexAlign.Center)
200      .shadow(ShadowStyle.OUTER_DEFAULT_SM)
201      .alignItems(VerticalAlign.Bottom)
202      .layoutWeight(1)
203    }
204  }
205}
206```
207
208## 效果展示
209
210![zh-cn_image_0000002211603692](figures/zh-cn_image_0000002211603692.png)
211