react native for OpenHarmony iconfont 图标不显示问题

问题描述

在 OpenHarmony 5.0.0.71 上安装应用后,iconfont 图标完全不显示。困扰了我好几天!!

根本原因

在 HarmonyOS/OpenHarmony 中使用自定义字体(包括 IconFont),必须在 ArkTS 侧显式注册字体 。仅靠 font.json 配置文件是不够的,这是与 Android/iOS 最大的区别。

根据 Ant Design Mobile RN 官方文档(Badge 组件示例),字体必须通过以下两步配置:

  1. resources/base/profile/font.json 中声明字体
  2. Index.etsRNApp 配置中通过 fontResourceByFontFamily 显式注册

正确的修复方案

1. 字体文件位置

确保字体文件在正确位置:

复制代码
harmony/entry/src/main/resources/rawfile/iconfont.ttf

2. 创建字体配置文件

位置harmony/entry/src/main/resources/base/profile/font.json

内容

json 复制代码
{
  "font": [
    {
      "name": "iconfont",
      "file": "rawfile/iconfont.ttf"
    }
  ]
}

关键点

  • file 路径必须是 rawfile/iconfont.ttf(相对于 resources 目录)
  • name 字段必须与后续 React Native 中使用的 fontFamily 一致

3. 在 Index.ets 中注册字体(关键步骤)

位置harmony/entry/src/main/ets/pages/Index.ets

修改内容

typescript 复制代码
RNApp({
  rnInstanceConfig: {
    createRNPackages,
    enableNDKTextMeasuring: true,
    enableBackgroundExecutor: false,
    enableCAPIArchitecture: true,
    arkTsComponentNames: [],
    // ⚠️ 关键:必须显式注册字体资源
    fontResourceByFontFamily: {
      'iconfont': $rawfile("iconfont.ttf"),
    }
  },
  // ...其他配置
})

说明

  • fontResourceByFontFamily 是必需的,这是 HarmonyOS 加载自定义字体的核心机制
  • 键名 'iconfont' 必须与 font.json 中的 name 字段一致
  • $rawfile("iconfont.ttf") 直接引用 rawfile 目录下的文件

4. React Native 组件使用

IconFont.tsx

typescript 复制代码
const IconFont: React.FC<IconFontProps> = ({ name, size = 16, color = '#000', style }) => {
  const iconCode = IconFontMap[name];

  // fontFamily 必须与 font.json 和 Index.ets 中注册的名称完全一致
  const fontFamily = Platform.select({
    harmony: 'iconfont',
    android: 'iconfont',
    ios: 'iconfont',
    default: 'iconfont',
  });

  return (
    <Text
      style={[
        {
          fontFamily: fontFamily,
          fontSize: size,
          color: color,
          includeFontPadding: false,
          textAlignVertical: 'center',
        },
        style,
      ]}
      allowFontScaling={false}>
      {iconCode}
    </Text>
  );
};

最终目录结构

复制代码
harmony/entry/src/main/
├── ets/pages/
│   └── Index.ets  ✅ 在此注册 fontResourceByFontFamily
├── resources/
│   ├── base/profile/
│   │   └── font.json  ✅ 字体配置文件
│   └── rawfile/
│       └── iconfont.ttf  ✅ 字体文件

关键要点

  1. 双重配置机制

    • font.json:声明字体元数据
    • Index.ets 中的 fontResourceByFontFamily:实际加载字体资源
  2. 路径一致性

    • font.json 中:"file": "rawfile/iconfont.ttf"(相对路径)
    • Index.ets 中:$rawfile("iconfont.ttf")(直接引用)
  3. 名称一致性

    • font.json 中的 name
    • Index.etsfontResourceByFontFamily 的键名
    • React Native 组件中的 fontFamily
    • 三者必须完全一致
  4. 不需要手动调用 API

    • 不需要在 EntryAbility.ets 中使用 font.registerFont()
    • 不需要在 Index.ets 的 aboutToAppear 中手动注册
    • 通过 fontResourceByFontFamily 配置即可自动加载

常见错误

❌ 错误做法 1:只配置 font.json

json 复制代码
// 只有这个配置是不够的
{
  "font": [{"name": "iconfont", "file": "rawfile/iconfont.ttf"}]
}

❌ 错误做法 2:font.json 路径错误

json 复制代码
{
  "font": [
    {"name": "iconfont", "file": "font/iconfont.ttf"}  // ❌ 错误路径
  ]
}

❌ 错误做法 3:缺少 fontResourceByFontFamily

typescript 复制代码
RNApp({
  rnInstanceConfig: {
    createRNPackages,
    enableNDKTextMeasuring: true,
    // ❌ 缺少 fontResourceByFontFamily 配置
    arkTsComponentNames: []
  },
})

✅ 正确做法:双重配置

json 复制代码
// font.json
{
  "font": [{"name": "iconfont", "file": "rawfile/iconfont.ttf"}]
}
typescript 复制代码
// Index.ets
RNApp({
  rnInstanceConfig: {
    // ...
    fontResourceByFontFamily: {
      'iconfont': $rawfile("iconfont.ttf"),
    }
  },
})

测试步骤

bash 复制代码
# 1. 清理并重新构建
cd harmony
hvigorw clean
hvigorw assembleHap

# 2. 安装到设备并测试图标显示

参考资料

  1. Ant Design Mobile RN 官方文档

    • Badge 组件示例中的字体配置方法
    • 明确要求在 Index.ets 中使用 fontResourceByFontFamily 注册字体
  2. OpenHarmony 字体系统

    • font.json:声明性配置
    • fontResourceByFontFamily:实际资源绑定

版本信息

  • OpenHarmony: 5.0.0.71
  • React Native OpenHarmony: 0.72.5
  • Ant Design Mobile RN: 3.2.0

总结

核心原理:HarmonyOS 的字体加载采用"声明 + 注册"的双重机制,缺一不可。这与 Android/iOS 只需将字体文件放入指定目录即可使用的方式完全不同。理解这一点是解决问题的关键。

相关推荐
2301_8227032023 分钟前
鸿蒙flutter三方库实战——教育与学习平台:Flutter Markdown
学习·算法·flutter·华为·harmonyos·鸿蒙
2301_822703203 小时前
开源鸿蒙跨平台Flutter开发:蛋白质序列特征提取:氨基酸组成与理化性质计算
flutter·华为·开源·harmonyos·鸿蒙
钛态3 小时前
Flutter 三方库 ethereum_addresses 的鸿蒙化适配指南 - 掌控区块链地址资产、精密校验治理实战、鸿蒙级 Web3 专家
flutter·harmonyos·鸿蒙·openharmony·ethereum_addresses
提子拌饭1334 小时前
开源鸿蒙跨平台Flutter开发:中小学百米跑信息记录表:基于 Flutter 的高精计时与运动学曲线引擎
flutter·华为·开源·harmonyos
2301_822703204 小时前
光影进度条:鸿蒙Flutter实现动态光影效果的进度条
算法·flutter·华为·信息可视化·开源·harmonyos
独特的螺狮粉4 小时前
城市空气质量简易指数查询卡片:鸿蒙Flutter框架 实现的空气质量查询应用
开发语言·flutter·华为·架构·harmonyos
互联网散修5 小时前
零基础鸿蒙应用开发第三十二节:JSON核心基础与文件的读写
华为·json·harmonyos
我的世界洛天依5 小时前
胡桃讲编程:华为鸿蒙系统能用 MT 管理器反编译吗?(安装包 + 系统根目录实战指南)
华为·harmonyos·机器翻译
李李李勃谦6 小时前
Flutter 框架跨平台鸿蒙开发 - 鲜花礼品配送
flutter·华为·harmonyos