You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中为Lottie动画配置自定义字体的正确方法(解决找不到字体报错)

为Lottie JSON文件设置自定义字体的正确方法

问题场景

我需要使用一个淡入淡出的Lottie文字动画,并将其中的默认字体替换为项目中的自定义字体。我的字体文件夹结构如下:
字体文件夹结构

但运行应用时抛出以下异常:

java.lang.RuntimeException: Font asset not found fonts/Arial.ttf
        at android.graphics.Typeface.createFromAsset(Typeface.java:965)
        at com.airbnb.lottie.manager.FontAssetManager.getFontFamily(FontAssetManager.java:87)
        at com.airbnb.lottie.manager.FontAssetManager.getTypeface(FontAssetManager.java:61)
        at com.airbnb.lottie.LottieDrawable.getTypeface(LottieDrawable.java:1094)
        at com.airbnb.lottie.model.layer.TextLayer.drawTextWithFont(TextLayer.java:238)
        at com.airbnb.lottie.model.layer.TextLayer.drawLayer(TextLayer.java:161)
        at com.airbnb.lottie.model.layer.BaseLayer.draw(BaseLayer.java:239)
        at com.airbnb.lottie.model.layer.CompositionLayer.drawLayer(CompositionLayer.java:120)
        at com.airbnb.lottie.model.layer.BaseLayer.draw(BaseLayer.java:239)
        at com.airbnb.lottie.LottieDrawable.drawWithOriginalAspectRatio(LottieDrawable.java:1247)
        at com.airbnb.lottie.LottieDrawable.drawInternal(LottieDrawable.java:393)
        at com.airbnb.lottie.LottieDrawable.draw(LottieDrawable.java:383)
        at android.widget.ImageView.onDraw(ImageView.java:1436)
        at android.view.View.draw(View.java:22350)
        at android.view.View.updateDisplayListIfDirty(View.java:21226)
        at android.view.View.draw(View.java:22081)
        at android.view.ViewGroup.drawChild(ViewGroup.java:4516)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4277)
        at android.view.View.draw(View.java:22353)
        at android.view.View.updateDisplayListIfDirty(View.java:21226)
        at android.view.View.draw(View.java:22081)
        at android.view.ViewGroup.drawChild(ViewGroup.java:4516)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4277)
        at android.view.View.updateDisplayListIfDirty(View.java:21217)
        at android.view.View.draw(View.java:22081)
        at android.view.ViewGroup.drawChild(ViewGroup.java:4516)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4277)
        at android.view.View.updateDisplayListIfDirty(View.java:21217)
        at android.view.View.draw(View.java:22081)
        at android.view.ViewGroup.drawChild(ViewGroup.java:4516)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4277)
        at android.view.View.updateDisplayListIfDirty(View.java:21217)
        at android.view.View.draw(View.java:22081)
        at android.view.ViewGroup.drawChild(ViewGroup.java:4516)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4277)
        at android.view.View.updateDisplayListIfDirty(View.java:21217)
        at android.view.View.draw(View.java:22081)
        at android.view.ViewGroup.drawChild(ViewGroup.java:4516)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4277)
        at android.view.View.draw(View.java:22353)
        at com.android.internal.policy.DecorView.draw(DecorView.java:806)
        at android.view.View.updateDisplayListIfDirty(View.java:21226)
        at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:559)
        at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:565)
        at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:642)
        at android.view.ViewRootImpl.draw(ViewRootImpl.java:4101)
        at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:3828)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3099)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1952)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8171)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:972)
        at android.view.Choreographer.doCallbacks(Choreographer.java:796)
        at android.view.Choreographer.doFrame(Choreographer.java:731)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

正确设置方法

1. 校验字体文件路径

错误提示找不到fonts/Arial.ttf,先确认:

  • 字体文件是否放在Android项目的src/main/assets/fonts/目录下,文件名(包括大小写)完全匹配,比如Arial.ttf不能写成arial.ttf。
  • 如果字体放在自定义assets目录,需要在app/build.gradle中配置路径:
    android {
        sourceSets {
            main {
                assets.srcDirs = ['src/main/assets'] // 替换为你的实际assets路径
            }
        }
    }
    

2. 修改Lottie JSON的字体配置

打开Lottie动画的JSON文件,找到assets -> fonts数组节点,将原字体的fFamily字段替换为你的字体文件名:

"assets": {
  "fonts": [
    {
      "fFamily": "Arial.ttf", // 替换为你的字体文件名
      "fName": "Arial",
      "fStyle": "Regular",
      "ascent": 1.0
    }
  ]
}

3. 代码手动映射字体(推荐)

如果不想修改JSON,或者JSON中的字体名称无法直接匹配,可通过代码手动关联:

LottieAnimationView lottieView = findViewById(R.id.your_lottie_view);

// 建立Lottie字体名与本地字体的映射
Map<String, Typeface> fontMap = new HashMap<>();
// 第一个参数是JSON中定义的fFamily值,第二个是本地字体的assets路径
fontMap.put("原字体家族名", Typeface.createFromAsset(getAssets(), "fonts/Arial.ttf"));

// 给LottieView设置字体映射
lottieView.setAssetFontMap(fontMap);

4. 常见排查点

  • 字体文件是否损坏:用系统字体工具打开确认文件有效。
  • 多模块项目:如果字体在其他模块,确保该模块的assets被主模块正确依赖。
  • 清理重建项目:有时候缓存会导致资源无法识别,执行Clean Project和Rebuild Project。

内容的提问来源于stack exchange,提问作者Arda Kaplan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 17:16:04