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.ets 的 RNApp 配置中通过 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.ets 中 fontResourceByFontFamily 的键名
    • 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 只需将字体文件放入指定目录即可使用的方式完全不同。理解这一点是解决问题的关键。

相关推荐
七月稻草人2 小时前
鸿蒙平板能当电脑第二块屏幕吗?ToDesk、向日葵镜像/副屏实测
华为·电脑·harmonyos
贾伟康3 小时前
【共创稿事节】HarmonyOS 7.0 Want隐式跳转:从接入到生产验证
性能优化·实战·harmonyos·arkts·arkui
NJPJI_Yang3 小时前
鸿蒙 HarmonyOS 7 应用内存优化:appMemoryOptimizer 释放 so 页缓存实战
pytorch·深度学习·harmonyos
熊猫钓鱼>_>5 小时前
三方库 NDK 原生模块跨平台适配与调试【鸿蒙心迹】
开发语言·华为·ai编程·harmonyos·鸿蒙·openharmony·鸿蒙心迹
前端小D5 小时前
React Native项目开发(iOS侧为例)
javascript·react native·react.js
行者-全栈开发16 小时前
【鸿蒙心迹】三方库移植(二)——CMake 交叉编译与符号冲突排查实录(HarmonyOS 7.x)
harmonyos·cmake·交叉编译·三方库移植·ohos·符号冲突
梦想不只是梦与想18 小时前
鸿蒙三方库源码调试
harmonyos·断点调试·三方源码调试
用户1179104883319 小时前
AI输出满屏井号星号?hmharness把Markdown渲染成终端表格 GitHub:swsgbl/hmharness
ai编程·harmonyos
大龄秃头程序员21 小时前
从源码里看懂 React Native 新架构:TurboModule 与 Fabric 到底是怎么跑起来的?
react native
了一12321 小时前
鸿蒙ArkWeb 长截图(滚动截图)技术方案总结
harmonyos