【问题标题】:"How to fix 'java.lang.IllegalArgumentException: Font has already been added' error in Android Q?"“如何修复 Android Q 中的 'java.lang.IllegalArgumentException: Font has been added' 错误?”
【发布时间】:2020-05-17 09:07:23
【问题描述】:

我必须在 Android Q 中尝试新功能(在 Android Q 和 AppCompat v1.1.0 中,连字符默认是关闭的)并且我还阅读了文档。当我按照 Android 博客中的说明进行操作时,它可以正常工作,但是当我尝试按照文档进行操作时,我发现了错误。

我只使用一个单一的字体系列。下面的代码正在运行:

tvTest.typeface = Typeface.CustomFallbackBuilder(
            FontFamily.Builder(
                Font.Builder(resources.assets, "aguafina_script.ttf").build()).build())
        .addCustomFallback(FontFamily.Builder(
                Font.Builder(resources.assets, "Font_Solid_900.otf").build()).build())
        .build()

但是当我尝试添加多个字体系列时,我得到了错误。

  Font regularFont = new Font.Builder("regular.ttf").build();
  Font boldFont = new Font.Builder("bold.ttf").build();
  FontFamily family = new FontFamily.Builder(regularFont)
      .addFont(boldFont).build();
  Typeface typeface = new Typeface.CustomFallbackBuilder(family)
      .setWeight(Font.FONT_WEIGHT_BOLD)  // Set bold style as the default style.
                                         // If the font family doesn't have bold style font,
                                         // system will select the closest font.
      .build();

以上代码在文档中给出 https://developer.android.com/reference/kotlin/android/graphics/Typeface.CustomFallbackBuilder.html

那么你能帮我解决这个错误吗?

【问题讨论】:

  • 请发布完整的错误日志..
  • java.lang.IllegalArgumentException: 字体 {path=null, style=FontStyle { weight=400, slant=0}, ttcIndex=0, axes=, localeList=, buffer=java.nio.DirectByteBuffer [pos=0 lim=656568 cap=656568]} 已经添加到 android.graphics.fonts.FontFamily$Builder.addFont(FontFamily.java:100)

标签: android


【解决方案1】:

当您尝试将具有相同样式和粗细的多种字体注册到相同字体中时,此错误会出现在 Android 10 的 androidx.core(或 core-ktx)版本 1.2.0 及更高版本中家庭。

虽然您的示例是以编程方式创建字体系列,但大多数开发人员在使用字体 XML 时会遇到此错误,所以让我们从它开始。

在字体 XML 中,我们不能有多个具有相同 fontStylefontWeight 属性的 font 元素。例如,以下 XML 会导致此错误,因为两个 font 元素的样式和权重值相同:

<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <font
        android:font="@font/gibson_regular"
        android:fontStyle="normal"
        android:fontWeight="400" />
    <font
        android:font="@font/gibson_bold"
        android:fontStyle="normal"
        android:fontWeight="400" />
</font-family>

即使font 的值不同(@font/gibson_regular vs @font/gibson_bold),fontStylefontWeight 是相同的,所以这会导致错误。

另外,请注意,如果您不提供 fontStylefontWeight 属性,则它们分别默认为 normal400,因此下一个示例也将失败:

<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <font
        android:font="@font/gibson_regular"
        android:fontStyle="normal"
        android:fontWeight="400" />
    <font
        android:font="@font/gibson_bold" />
</font-family>

要解决此问题,请确保每个font 元素的fontStylefontWeight组合 是唯一的。例如,如果我们为gibson_bold字体正确设置fontWeight,我们将避免错误:

<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <font
        android:font="@font/gibson_regular"
        android:fontStyle="normal"
        android:fontWeight="400" />
    <font
        android:font="@font/gibson_bold"
        android:fontStyle="normal"
        android:fontWeight="700" />
</font-family>

现在,当以编程方式构建它时,如上所述,同样的规则适用。看起来您引用的 API 文档尚未更新以匹配源代码实际执行的操作。您的示例现在应该如下所示:

val regularFont: Font = Font.Builder(resources.assets,"regular.ttf").build()
val boldFont: Font = Font.Builder(resources.assets, "bold.ttf").build()
val family: FontFamily = FontFamily.Builder(regularFont).addFont(boldFont).build()

val typeface: Typeface = CustomFallbackBuilder(family)
    .setStyle(FontStyle(FONT_WEIGHT_BOLD, FONT_SLANT_UPRIGHT))
    .build()

当像这样以编程方式编写它时,Android 在通过 Font.Builder 加载字体时似乎会正确记录字体的粗细和样式,只要 regular.ttfbold.ttf 的粗细和样式不同,这段代码就可以正常工作了。

但是,如果两种字体具有相同的粗细和样式,或者如果您手动指定字体和样式相同,例如如果您要在粗体字体上调用 setWeight(400),您仍然会出现此异常。

总之,当使用字体 XML 时,请始终为每种字体指定 fontStylefontWeight。无论您是使用 XML 编写内容还是以编程方式构建它们,请确保字体系列中每种字体的粗细和样式组合都是唯一的。

【讨论】:

  • 谢谢@Dave Leeds。一个很好解释的答案。
  • 好答案。我必须使用两种字体来支持 api 25 及更低版本。改变字体的重量对我有用
  • 我欠你我的理智先生。
  • 这可能为我节省了一三个小时的调试时间。
【解决方案2】:

免责声明:我的情况和你的不一样,但错误是一样的。我只是想帮助解决这个问题的人,因为这是唯一提到错误的人。也许它也对 OP 有帮助。

事实证明,罪魁祸首是我的 font-family xml 文件。即使我的文件在 Android 9 及更低版本上运行良好,但在 Android 10(Q) 上却失败了。原因是我将不止一种 fontStyles 定义为“正常”:

<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto">

    <font
        app:fontStyle="normal"
        app:font="@font/dosis_regular"/>

    <font
        app:fontStyle="normal"
        app:font="@font/dosis_bold"/>

    <font
        app:fontStyle="normal"
        app:font="@font/dosis_light"/>

</font-family>

在我将其更改为仅其中一个“正常”之后,它工作得很好。

<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto">

    <font
        app:fontStyle="normal"
        app:font="@font/dosis_regular"/>

    <font
        app:fontWeight="700"
        app:font="@font/dosis_bold"/>

    <font
        app:fontStyle="italic"
        app:font="@font/dosis_light"/>

</font-family>

【讨论】:

  • 我们在其中一个模块中添加了 androidx.core:core-ktx:1.2.0 依赖项后,它才开始在 Android 10 中发生。删除此依赖项或您的解决方案都可以为我们解决崩溃问题。
【解决方案3】:

1)单击app作为根文件夹,右键单击它并选择:新建->文件夹->创建资产文件夹, 你会得到一个对话框:为资产创建一个源根目录

2)在您的资产文件夹中包含 .ttf 文件

3)像这样在你的活动或片段中使用

TextView name = (TextView) findViewById(R.id.tv_date);
    Typeface pick_text = Typeface.createFromAsset(itemView.getContext().getAssets(),  "fonts/OpenSans-Semibold.ttf");
    name.setTypeface(pick_text);

    TextView desc = (TextView) findViewById(R.id.tv_orderid);
    Typeface desc_text = Typeface.createFromAsset(itemView.getContext().getAssets(),  "fonts/NevisBold-KGwl.ttf");
    desc.setTypeface(desc_text);

【讨论】:

    猜你喜欢
    • 2021-11-09
    • 1970-01-01
    • 2017-10-16
    • 2013-05-04
    • 1970-01-01
    • 2019-04-25
    • 2021-12-25
    • 2020-10-13
    • 1970-01-01
    相关资源
    最近更新 更多