在应用开发中,字体是用户界面的核心视觉元素之一,也是构建良好用户体验的关键要素之一,直接影响应用界面的美观性、可读性和用户体验。
ArkUI提供了全面的字体控制能力,如自定义设置字体大小和字重;支持通过registerFont()方法注册TTF和OTF自定义字体文件,或下载字体文件到沙箱内注册使用,实现字体的动态切换;支持省略号、自动缩放和换行控制等多种文本内容溢出处理策略,使开发者能够精细调整应用中的字体表现,满足应用多样化的设计需求。
本文将介绍以下字体设置场景的实现:
场景描述
在字体设置中,点击选择字体列表中的某个字体后,页面的字体样式会发生变化。在退出应用重新进入后,默认显示退出前选择的字体样式。

实现原理
registerFont()方法可以在字体管理器中注册自定义字体,支持注册TTF格式和OTF格式的字体文件。
preferences (用户首选项)则为应用提供了处理Key-Value键值型数据的能力,支持应用持久化轻量级数据,以及数据的修改和查询。
开发步骤
- 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();
- export default class EntryAbility extends UIAbility {
- onCreate(_want: Want, _launchParam: AbilityConstant.LaunchParam): void {
- // Get preference instance
- PreferenceUtils.getTextFontPreference(this.context);
- // ...
- }
-
- // ...
- }
在使用时,需要通过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}`);
- }
- }
- @StorageLink('fontOffset') fontOffset: string = '';
- // ...
-
- aboutToAppear() {
- // ...
- // Get font data from preferences
- this.fontOffset = PreferenceUtils.getFont();
- // Register font
- registerMyFont(this.getUIContext());
- }
- MenuItem({
- content: item === '' ? $r('app.string.system_default') : item,
- endIcon: this.fontOffset === item ? $r('app.media.checkmark') : ''
- })
- .onChange(() => {
- this.fontOffset = item;
- PreferenceUtils.saveModifyFont(item);
- })
- // 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 Sans,当fontFamily属性被显式设置为空字符串时,实际生效字体与不设置fontFamily时的效果一致,会回退到默认字体,字体样式、字重等其它属性可正常应用。
开发步骤
- Menu() {
- ForEach(this.menuItemArr, (item: string) => {
- MenuItem({
- content: item === '' ? $r('app.string.system_default') : item,
- endIcon: this.fontOffset === item ? $r('app.media.checkmark') : ''
- })
- .onChange(() => {
- this.fontOffset = item;
- PreferenceUtils.saveModifyFont(item);
- })
- }, (item: string) => item)
- }
- // ...
- Text($r('app.string.preview_text'))
- // ...
- .fontFamily(this.fontOffset)
场景描述
在设置页面中,点击打开Toggle按钮,使页面字体大小跟随系统设置发生变化。此时,自定义字体大小和字重的Slider将被禁用,无法滑动或点击。

实现原理
在应用的app.json5配置文件中,configuration标签是用于标识应用字体大小跟随系统变更的配置文件。当configuration的fontSizeScale属性取值为followSystem,且字体大小fontSize属性使用fp为像素单位时,在改变系统设置中的字体大小缩放比例后,应用中的字体也会相应变化。
开发步骤
fontSizeScale属性取值(默认为nonFollowSystem不跟随系统):
- {
- "configuration": {
- "fontSizeScale": "followSystem",
- "fontSizeMaxScale": "2"
- }
- }
- {
- "app": {
- "bundleName": "com.example.textdisplayfont",
- "vendor": "example",
- "versionCode": 1000000,
- "versionName": "1.0.0",
- "icon": "$media:layered_image",
- "label": "$string:app_name",
- "configuration": "$profile:configuration"
- }
- }
- Toggle({ type: ToggleType.Switch, isOn: this.toggleState })
- .onChange((isOn: boolean) => {
- this.toggleState = isOn;
- })
当toggleState为true时,表示跟随系统,Slider不可点击或滑动;为false时,表示不跟随系统,Slider可以点击或滑动。
- Slider({
- min: -4,
- max: 4,
- value: this.fontSizeOffset,
- style: SliderStyle.InSet
- })
- .width('90%')
- .margin({ top: 12 })
- .enabled(!this.toggleState)
场景描述
在设置页中点击关闭Toggle按钮,通过Slider组件可以调整页面字体大小。在系统设置中调整字体大小,页面字体不会发生变化。

实现原理
在应用的app.json5配置文件中,通过configuration标签标识了应用字体跟随系统设置,当字体大小fontSize属性使用屏幕物理像素单位px时,页面字体大小将不再受系统设置的影响。
开发步骤
- // Convert fp to px
- export function fp2pxUtil(fp: number): string {
- const pxStr: string = 'px';
- let pxVal: number = 0;
- let displayClass: display.Display | null = null;
- try {
- displayClass = display.getDefaultDisplaySync();
- pxVal = fp * (displayClass.densityDPI / 160);
- } catch (err) {
- let error = err as BusinessError;
- hilog.error(0x0000, TAG, `get densityDPI failed. code: ${error.code}, message:${err.message}`);
- }
- return pxVal + pxStr;
- }
- Text($r('app.string.setting'))
- .width('100%')
- .fontWeight(700)
- .fontSize(this.toggleState ? 26 : fp2pxUtil(26))
- // System environment change information
- let envCallback: EnvironmentCallback = {
- onConfigurationUpdated(config) {
- envFont.fontSizeScale = config.fontSizeScale; // Font size scaling ratio
- envFont.fontWeightScale = config.fontWeightScale; // Font thickness scaling ratio
- },
- onMemoryLevel(level) {
- hilog.info(DOMAIN, TAG, `onMemoryLevel level: ${level}`);
- }
- }
- let appContext = this.context.getApplicationContext();
- // Register to monitor changes in the system environment
- callbackId = appContext.on('environment', envCallback);