跳到主要内容

自定义字体

当应用需要支持自定义字体时,开发者可通过ReaderSetting的fontPath属性,实现对阅读内容字体的实时修改。

自定义字体文件支持两种存放路径:

业务流程

接口说明

自定义字体主要涉及3个接口,具体介绍如下表所示。

接口名描述
setPageConfig(pageConfig: ReaderSetting): void设置或者修改页面排版属性。
on('resourceRequest')注册资源请求回调,如果设置了自定义背景,字体时,排版引擎会通过此接口获取对应的资源ArrayBuffer。
off('resourceRequest')注销资源请求回调接口,可在页面销毁时调用。

开发准备

  • 进行自定义字体之前,请先确保已经“构建阅读器”。
  • 已经准备好字体资源,并放在对应的目录当中。

开发步骤

  1. 导入相关模块。

    import { fileIo as fs } from '@kit.CoreFileKit';
    import { common } from '@kit.AbilityKit';
    import { hilog } from '@kit.PerformanceAnalysisKit';
  2. 定义字体文件存放路径:

    • 若资源放在项目resources/rawfile/fonts文件夹下。

      let filePath: string = 'fonts/SourceHanSerifCN-VF.ttf';
    • 若资源放在应用沙箱目录下。

      let filePath: string = this.getUIContext().getHostContext()!.filesDir + '/fonts/SourceHanSerifCN-VF.ttf'
  3. 通过ReaderSetting的fontName和fontPath属性设置自定义字体的名称及所在的路径,并调用ReaderComponentController组件控制器的setPageConfig接口,重新渲染界面。

    this.readerSetting.fontName = '思源宋体';
    // 路径为上述两种之一
    this.readerSetting.fontPath = filePath;
    this.readerComponentController.setPageConfig(this.readerSetting);
  4. 注册排版引擎资源请求接口,并返回相应资源。

    当排版引擎检测到是自定义字体场景时,会通过接口请求字体资源。开发者需要根据返回的文件路径,判断是否为请求字体资源。如果是,则根据字体资源所在的路径,返回对应的ArrayBuffer。

    aboutToAppear(): void {
    // 注册资源请求回调
    this.readerComponentController.on('resourceRequest', this.resourceRequest);
    }

    aboutToDisappear(): void {
    // 注销资源请求回调
    this.readerComponentController.off('resourceRequest');
    }

    private isFont(filePath: string): boolean {
    let options = [".ttf", ".woff2", ".otf"];
    let path = filePath.toLowerCase();
    let result = path.indexOf(options[0]) != -1 || path.indexOf(options[1]) != -1 || path.indexOf(options[2]) != -1;
    hilog.info(0x0000, 'testTag', 'isFont = ' + result);
    return result;
    }

    /**
    * 资源请求回调
    */
    private resourceRequest: bookParser.CallbackRes<string, ArrayBuffer> = (filePath: string): ArrayBuffer => {
    hilog.info(0x0000, 'testTag', 'resourceRequest : filePath = ' + filePath);
    if (filePath.length === 0) {
    return new ArrayBuffer(0);
    }
    if (!this.isFont(filePath)) {
    return new ArrayBuffer(0);
    }
    try {
    let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
    // 获取资源路径resources/rawfile/fonts下的字体文件Uint8Array数据
    let value: Uint8Array = context.resourceManager.getRawFileContentSync(this.readerSetting.fontPath);
    hilog.info(0x0000, 'testTag', 'resourceRequest : get other resource succeeded ');
    return value.buffer as ArrayBuffer;
    } catch (error) {
    let code = (error as BusinessError).code;
    let message = (error as BusinessError).message;
    hilog.error(0x0000, 'testTag',
    `resourceRequest : get other resource failed, error code: ${code}, message: ${message}.`);
    }
    // 如果在资源路径resources/rawfile/fonts下获取字体文件数据失败,则去沙箱目录下获取字体文件数据
    return this.loadFileFromPath(this.readerSetting.fontPath);
    }

    private loadFileFromPath(filePath: string): ArrayBuffer {
    try {
    let stats = fs.statSync(filePath);
    let file = fs.openSync(filePath, fs.OpenMode.READ_ONLY);
    let buffer = new ArrayBuffer(stats.size);
    fs.readSync(file.fd, buffer);
    fs.closeSync(file);
    return buffer;
    } catch (err) {
    hilog.error(0x0000, 'testTag', "mkdir failed with error message: ", err.message, ", error code: ", err.code);
    return new ArrayBuffer(0);
    }
    }