HarmonyOS鸿蒙Next字体

HarmonyOS鸿蒙Next字体

自定义字体无法全局使用如何处理

4 回复

更多关于HarmonyOS鸿蒙Next字体的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


registerFont()方法可以在字体管理器中注册自定义字体,支持注册TTF格式和OTF格式的字体文件。

preferences (用户首选项)则为应用提供了处理Key-Value键值型数据的能力,支持应用持久化轻量级数据,以及数据的修改和查询。

开发步骤

  1. 创建首选项工具类PreferenceUtils,在类中定义如下方法:
    • getTextFontPreference()方法:在其中通过getPreferencesSync()方法获取首选项实例。
    • saveModifyFont()方法:在其中通过putSync()方法将传入的字体信息数据写入首选项实例中,再使用flush()方法将数据持久化存储。
    • getFont()方法:在其中通过getSync()方法从首选项实例中获取存储的数据。
export class PreferenceUtils {
  preference?: preferences.Preferences;
  // Get Preferences instance
  getTextFontPreference(context: Context) {
    try {
      this.preference = preferences.getPreferencesSync(context, { name: 'TextFontPreference' });
      hilog.info(0x0000, TAG, 'create preference success');
    } catch (err) {
      let error = err as BusinessError;
      hilog.error(0x0000, TAG, `create preference failed. code: ${error.code}, message:${err.message}`);
    }
  }
  // ...
  // Save Font
  saveModifyFont(textFont: string) {
    try {
      this.preference?.putSync(TEXT_FONT, textFont);
      this.preference?.flush((err: BusinessError) => {
        if (err) {
          hilog.error(0x0000, TAG, `Failed to flush. code:${err.code}, message:${err.message}`);
          return;
        }
        hilog.info(0x0000, TAG, 'Succeeded in flushing.');
      })
    } catch (err) {
      let error = err as BusinessError;
      hilog.error(0x0000, TAG,
        `putSync or flush font preference data failed. code: ${error.code}, message:${err.message}`);
    }
  }
  // Get Font
  getFont(): string {
    let textFont: string = '';
    try {
      textFont = this.preference?.getSync(TEXT_FONT, '') as string;
    } catch (err) {
      let error = err as BusinessError;
      hilog.error(0x0000, TAG, `getSync font preference data failed. code: ${error.code}, message:${err.message}`);
    }
    return textFont;
  }
}
export default new PreferenceUtils();

2、在EntryAbility的onCreate()生命周期中,调用getTextFontPreference()方法获取首选项实例。

export default class EntryAbility extends UIAbility {
  onCreate(_want: Want, _launchParam: AbilityConstant.LaunchParam): void {
    // Get preference instance
    PreferenceUtils.getTextFontPreference(this.context);
    // ...
  }
  // ...
}

3、定义registerMyFont()方法注册自定义字体。

在使用时,需要通过UIContext中的getFont()方法获取当前UI上下文关联的Font对象,再通过该对象调用registerFont()方法注册字体。

// Register font
export function registerMyFont(uiContext: UIContext) {
  try {
    // Register HarmonyOS Italic font through registrant Font
    uiContext.getFont().registerFont({
      familyName: $r('app.string.HarmonyOS_Italic'),
      familySrc: $rawfile('HarmonyOS_SansItalic.ttf')
    });
    // Register HarmonyOS Condensed font through registrant Font
    uiContext.getFont().registerFont({
      familyName: $r('app.string.HarmonyOS_Condensed'),
      familySrc: $rawfile('HarmonyOS_Condensed.ttf')
    });
  } catch (err) {
    let error = err as BusinessError;
    hilog.error(0x0000, TAG, `registerFont failed. code: ${error.code}, message:${err.message}`);
  }
}

4、通过@StorageLink装饰变量fontOffset,标识当前选择的字体。在页面aboutToAppear()生命周期中,调用registerMyFont()方法并传入UIContext,注册自定义字体,并通过PreferenceUtils类调用getFont()方法,获取首选项中存储的数据,赋值给fontOffset,实现退出重新进入应用后显示退出前选择的字体。

[@StorageLink](/user/StorageLink)('fontOffset') fontOffset: string = '';
// ...
aboutToAppear() {
  // ...
  // Get font data from preferences
  this.fontOffset = PreferenceUtils.getFont();
  // Register font
  registerMyFont(this.getUIContext());
}

5、在MenuItem的onChange()事件中修改fontOffset的值,并通过saveModifyFont()方法,将选择的字体数据写入首选项并持久化存储。

MenuItem({
  content: item === '' ? $r('app.string.system_default') : item,
  endIcon: this.fontOffset === item ? $r('app.media.checkmark') : ''
})
  .onChange(() => {
    this.fontOffset = item;
    PreferenceUtils.saveModifyFont(item);
  })

6、通过fontFamily属性传入变量fontOffset,使用注册的自定义字体改变字体样式。

// Example Text Content
Column() {
  Text($r('app.string.preview_text'))
    // ...
    .fontFamily(this.fontOffset)
}
.width('100%')
.padding(12)
.margin({ top: 35 })
.backgroundColor('#FFF')
.borderRadius(16)

HarmonyOS Next字体系统采用全新设计的HarmonyOS Sans字体,支持可变字体特性。该系统提供多语言支持,包括中文、拉丁文、西里尔文等。字体渲染引擎经过优化,支持动态字重调整和智能抗锯齿技术。开发者可通过font-family属性调用系统字体,并支持自定义字体引入。字体管理通过统一的资源管理系统实现,支持按需加载和动态更新。

在HarmonyOS Next中,自定义字体无法全局生效,通常是因为未在应用的全局样式文件(如AppScope/resources/base/element/string.json或通过ResourceManager)中进行正确配置。

核心步骤:

  1. 放置字体文件:将字体文件(如.ttf.otf)放入AppScope/resources/base/media/目录下。
  2. string.json中声明:在AppScope/resources/base/element/string.json文件中,为字体创建资源引用。
    {
      "string": [
        {
          "name": "custom_font_family",
          "value": "YourFontName"
        }
      ]
    }
    
  3. 全局应用字体:在全局UI样式中(例如AppScope/resources/base/profile/main_pages.json或在页面的aboutToAppear中通过setFontFamily设置),使用声明的字体资源。
    {
      "css": [
        {
          "font-family": "$string:custom_font_family"
        }
      ]
    }
    
    在ArkTS中:
    import { ResourceManager } from '@ohos.resourceManager';
    // 获取ResourceManager实例后
    let fontFamily = resMgr.getString($r('app.string.custom_font_family').id);
    // 然后应用于组件或全局样式
    

关键检查点:

  • 字体文件格式需为系统支持的类型(如.ttf)。
  • string.json中的name需与引用时$string:后的名称一致。
  • 字体文件名无需与value中的字体名严格相同,但value需是字体内部元数据定义的名称(可通过字体工具查看)。
  • 部分组件可能需要单独设置fontFamily属性。

若按上述配置后仍无效,请检查字体文件是否损坏,或尝试在单个组件上应用字体以确认基础功能正常。

回到顶部