1# 自定义字体的注册和使用(ArkTS) 2<!--Kit: ArkGraphics 2D--> 3<!--Subsystem: Graphics--> 4<!--Owner: @oh_wangxk; @gmiao522; @Lem0nC--> 5<!--Designer: @liumingxiang--> 6<!--Tester: @yhl0101--> 7<!--Adviser: @ge-yafang--> 8## 场景介绍 9 10自定义字体是指开发者根据应用需求创建或选择的字体,通常用于实现特定的文字风格或满足独特的设计要求。当应用需要使用特定的文本样式和字符集时,可以注册并使用自定义字体进行文本渲染。 11 12## 实现流程 13 14**自定义字体的注册**是指将字体文件(如ttf、otf文件等)从应用资源注册到系统中,使得应用能够使用这些字体进行文本渲染。注册过程是将字体文件通过字体管理接口注册到系统字体库中,以便在应用中进行调用。 15 16**自定义字体的使用**是指在应用中显式指定使用已注册的自定义字体进行文本渲染。开发者可以根据需要选择特定的文本样式(如常规、粗体、斜体等),并将其应用到UI元素、文本控件或其他文本展示区域,以满足设计要求并提供视觉效果的一致性。 17 18 19## 接口说明 20 21自定义字体注册和使用的常用接口如下表所示,详细接口说明请见[@ohos.graphics.text (文本模块)](../reference/apis-arkgraphics2d/js-apis-graphics-text.md)。 22 23| 接口 | 描述 | 24| -------- | -------- | 25| loadFontSync(name: string, path: string \| Resource): void | 同步接口,将路径对应的文件,以name作为使用的别名,注册自定义字体。<br/>**说明:**<br/>需保证使用自定义字体时,自定义字体已完成注册,非性能严格要求场景下,建议使用同步接口。 | 26| loadFont(name: string, path: string \| Resource): Promise<void> | 使用指定的别名和文件路径注册对应字体,使用Promise异步回调。此接口从API version 14开始支持。 | 27| unloadFontSync(name: string): void | 同步接口,注销指定别名的字体。此接口从API version 20开始支持。 | 28| unloadFont(name: string): Promise\<void\> | 使用指定的别名注销对应字体,使用Promise异步回调。此接口从API version 20开始支持。 | 29 30## 开发步骤 31 321. 导入依赖的相关模块。 33 34 ```ts 35 import { NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI' 36 import { UIContext } from '@kit.ArkUI' 37 import { text } from '@kit.ArkGraphics2D' 38 ``` 39 402. 注册自定义字体。有以下两种方式: 41 42 ```ts 43 // 注册自定义字体 44 let fontCollection = text.FontCollection.getGlobalInstance() 45 // 方式一:/system/fonts/myFontFile.ttf文件仅为示例路径,应用根据自身实际填写文件路径 46 fontCollection.loadFontSync('myFamilyName0', 'file:///system/fonts/myFontFile.ttf') 47 48 // 方式二:确保已经将自定义字体myFontFile.ttf文件放在本应用工程的entry/src/main/resources/rawfile目录 49 fontCollection.loadFontSync('myFamilyName1',$rawfile('myFontFile.ttf')) 50 ``` 51 523. 使用自定义字体。 53 54 ```ts 55 // 填写注册自定义字体时传入的字体家族名 56 let myFontFamily: Array<string> = ["myFamilyName0"] 57 // 设置文本样式 58 let myTextStyle: text.TextStyle = { 59 color: { alpha: 255, red: 255, green: 0, blue: 0 }, 60 fontSize: 100, 61 // 在文本样式中加入可使用的自定义字体 62 fontFamilies: myFontFamily 63 }; 64 ``` 65 664. 创建段落样式,并使用字体管理器实例构造段落生成器ParagraphBuilder实例。 67 68 ```ts 69 // 创建一个段落样式对象,以设置排版风格 70 let myParagraphStyle: text.ParagraphStyle = {textStyle: myTextStyle} 71 // 创建一个段落生成器 72 let paragraphBuilder: text.ParagraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection); 73 ``` 74 755. 生成段落。 76 77 ```ts 78 // 在段落生成器中设置文本样式 79 paragraphBuilder.pushStyle(myTextStyle); 80 // 在段落生成器中设置文本内容 81 paragraphBuilder.addText("Custom font test"); 82 // 通过段落生成器生成段落 83 let paragraph = paragraphBuilder.build(); 84 ``` 85 866. 如果需要释放自定义字体,可以使用unloadFontSync接口。 87 88 ```ts 89 // 注销自定义字体 90 fontCollection.unloadFontSync(familyName) 91 // 注销之后需要刷新使用该fontCollection的节点 92 newNode.invalidate() 93 ``` 94 95## 完整示例 96 97这里以使用自定义注册字体方式一为例绘制“Custom font test”文本,并提供如下完整示例。 98 99请保证自定义字体文件已放置到设备正确的路径下。 100 101```ts 102// Index.ets 103import { NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI' 104import { UIContext } from '@kit.ArkUI' 105import { text } from '@kit.ArkGraphics2D' 106 107// 获取全局字体集实例 108let fontCollection = text.FontCollection.getGlobalInstance() //获取Arkui全局FC 109const familyName = "myFamilyName" 110 111// 创建一个自定义的渲染节点类,用于绘制文本 112class MyRenderNode extends RenderNode { 113 async draw(context: DrawContext) { 114 // 创建画布canvas对象 115 const canvas = context.canvas 116 // 使用自定义字体 117 let myFontFamily: Array<string> = [familyName] // 如果已经注册自定义字体,填入自定义字体的字体家族名 118 // 设置文本样式 119 let myTextStyle: text.TextStyle = { 120 color: { 121 alpha: 255, 122 red: 255, 123 green: 0, 124 blue: 0 125 }, 126 fontSize: 30, 127 // 在文本样式中加入可使用的自定义字体 128 fontFamilies: myFontFamily 129 }; 130 // 创建一个段落样式对象,以设置排版风格 131 let myParagraphStyle: text.ParagraphStyle = { 132 textStyle: myTextStyle, 133 align: 3, 134 wordBreak: text.WordBreak.NORMAL 135 }; 136 // 创建一个段落生成器 137 let ParagraphGraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection) 138 // 在段落生成器中设置文本样式 139 ParagraphGraphBuilder.pushStyle(myTextStyle); 140 // 在段落生成器中设置文本内容 141 ParagraphGraphBuilder.addText("Custom font test"); 142 // 通过段落生成器生成段落 143 let paragraph = ParagraphGraphBuilder.build(); 144 // 设置段落宽度为1000px 145 paragraph.layoutSync(1000); 146 paragraph.paint(canvas, 0, 400); 147 } 148} 149 150// 创建并初始化渲染节点实例 151const newNode = new MyRenderNode(); 152// 设置渲染节点的位置和尺寸 153newNode.frame = { 154 x: 0, 155 y: 0, 156 width: 400, 157 height: 600 158}; 159 160 161class MyNodeController extends NodeController { 162 private rootNode: FrameNode | null = null; 163 164 makeNode(uiContext: UIContext): FrameNode { 165 this.rootNode = new FrameNode(uiContext) 166 if (this.rootNode == null) { 167 return this.rootNode 168 } 169 const renderNode = this.rootNode.getRenderNode() 170 if (renderNode != null) { 171 renderNode.frame = { 172 x: 0, 173 y: 0, 174 width: 300, 175 height: 50 176 } 177 renderNode.pivot = { x: 0, y: 0 } 178 } 179 return this.rootNode 180 } 181 182 addNode(node: RenderNode): void { 183 if (this.rootNode == null) { 184 return 185 } 186 const renderNode = this.rootNode.getRenderNode() 187 if (renderNode != null) { 188 renderNode.appendChild(node) 189 } 190 } 191 192 clearNodes(): void { 193 if (this.rootNode == null) { 194 return 195 } 196 const renderNode = this.rootNode.getRenderNode() 197 if (renderNode != null) { 198 renderNode.clearChildren() 199 } 200 } 201} 202 203@Entry 204@Component 205struct RenderTest { 206 private myNodeController: MyNodeController = new MyNodeController() 207 208 build() { 209 Column() { 210 Row() { 211 // 如果使用getGlobalInstance的fontCollection注册字体,使用对应family name的组件会自动刷新 212 Text("Text Component") 213 .fontFamily(familyName) 214 NodeContainer(this.myNodeController) 215 .height('100%') 216 .onAppear(() => { 217 this.myNodeController.clearNodes() 218 this.myNodeController.addNode(newNode) 219 }) 220 } 221 .height('90%') 222 .backgroundColor(Color.White) 223 224 Row() { 225 Button("load font") 226 .fontSize('16fp') 227 .fontWeight(500) 228 .margin({ bottom: 24, right: 12 }) 229 .onClick(() => { 230 // 注册自定义字体 231 fontCollection.loadFontSync(familyName, 'file:///system/fonts/NotoSansMalayalamUI-SemiBold.ttf') 232 // 注册之后需要刷新使用该fontCollection的节点 233 newNode.invalidate() 234 }) 235 .width('30%') 236 .height(40) 237 .shadow(ShadowStyle.OUTER_DEFAULT_LG) 238 Button("unload font") 239 .fontSize('16fp') 240 .fontWeight(500) 241 .margin({ bottom: 24, right: 12 }) 242 .onClick(() => { 243 // 注销自定义字体 244 fontCollection.unloadFontSync(familyName) 245 // 注销之后需要刷新使用该fontCollection的节点 246 newNode.invalidate() 247 }) 248 .width('30%') 249 .height(40) 250 .shadow(ShadowStyle.OUTER_DEFAULT_LG) 251 } 252 .width('100%') 253 .justifyContent(FlexAlign.Center) // 设置当前Row容器内子元素在主轴上居中对齐 254 .shadow(ShadowStyle.OUTER_DEFAULT_SM) // 设置Row容器外阴影效果 255 .alignItems(VerticalAlign.Bottom) // 设置当前Row容器内子元素在交叉轴(垂直方向)上的对齐方式为底部对齐 256 .layoutWeight(1) // 设置当前Row在父容器Column中的布局权重为1 257 } 258 } 259} 260``` 261 262## 效果展示 263 264 265 266