如何为 XML 中的字体使用指定的粗细

How to use specified weights for fonts in XML

使用 Fonts in XML 功能,您可以为字体系列指定各种字体粗细。例如:

<?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/archivo_narrow_regular" android:fontWeight="400" android:fontStyle="normal"
        app:font="@font/archivo_narrow_regular" app:fontWeight="400" app:fontStyle="normal"/>

    <font android:font="@font/archivo_narrow_regular_italic" android:fontWeight="400" android:fontStyle="italic"
        app:font="@font/archivo_narrow_regular_italic" app:fontWeight="400" app:fontStyle="italic"/>

    <font android:font="@font/archivo_narrow_medium" android:fontWeight="500" android:fontStyle="normal"
        app:font="@font/archivo_narrow_medium" app:fontWeight="500" app:fontStyle="normal"/>

    <font android:font="@font/archivo_narrow_medium_italic" android:fontWeight="500" android:fontStyle="italic"
        app:font="@font/archivo_narrow_medium_italic" app:fontWeight="500" app:fontStyle="italic"/>

    <font android:font="@font/archivo_narrow_semibold" android:fontWeight="600" android:fontStyle="normal"
        app:font="@font/archivo_narrow_semibold" app:fontWeight="600" app:fontStyle="normal"/>

    <font android:font="@font/archivo_narrow_semibold_italic" android:fontWeight="600" android:fontStyle="italic"
        app:font="@font/archivo_narrow_semibold_italic" app:fontWeight="600" app:fontStyle="italic"/>

    <font android:font="@font/archivo_narrow_bold" android:fontWeight="700" android:fontStyle="normal"
        app:font="@font/archivo_narrow_bold" app:fontWeight="700" app:fontStyle="normal"/>

    <font android:font="@font/archivo_narrow_bold_italic" android:fontWeight="700" android:fontStyle="italic"
        app:font="@font/archivo_narrow_bold_italic" app:fontWeight="700" app:fontStyle="italic"/>

</font-family>

但我不知道如何实际使用这些权重;在 XML (layout/style) 文件中,或在 Java 代码中。 TextView 没有可用的 fontWeight 属性,Typeface object created from ResourcesCompat.getFont(context, R.font.archivo_narrow) 也没有提到字体粗细。

我知道我可以指定特定的字体资源(即 R.font.archivo_narrow_semibold),但是 font-family 中的 fontWeight 属性有什么意义?


更新

一个新的静态 create(Typeface family, int weight, boolean italic) method was added in API Level 28, along with a getWeight() 实例方法。这最终使得在 Java 代码中使用 fontWeight 属性成为可能;虽然仅适用于 API 28 级及以上,但我在支持库中没有找到任何类似物。

这很有用——表明 fontWeight 属性在过去没有任何作用——但我真的很希望能够在 XML 样式中使用权重。

看起来 android 遵循 android 应用的字体管理和大小调整 Web 标准。

“font-weight”属性用于定义字体的粗细,例如常规或粗体。

但对于所有其他权重,使用 100 到 900 的数值范围。 Web 字体面临的挑战之一是大多数 Web 浏览器不能正确支持普通和粗体以外的字体粗细。下表描述了权重到数字定义的可能映射:

100    Extra Light or Ultra Light
200    Light or Thin
300    Book or Demi
400    Normal or Regular
500    Medium
600    Semibold, Demibold
700    Bold
800    Black, Extra Bold or Heavy
900    Extra Black, Fat, Poster or Ultra Black

您可以阅读有关字体粗细的更多信息here


cc_montserrat_bold.xml

<?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/montserrat_bold"
        android:fontStyle="normal"
        android:fontWeight="700"
        app:font="@font/montserrat_bold"
        app:fontStyle="normal"
        app:fontWeight="700" />
    <font
        android:font="@font/montserrat_bolditalic"
        android:fontStyle="italic"
        android:fontWeight="700"
        app:font="@font/montserrat_bolditalic"
        app:fontStyle="italic"
        app:fontWeight="700" />

</font-family>

cc_montserrat_regular.xml

<?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/montserrat_regular"
        android:fontStyle="normal"
        android:fontWeight="400"
        app:font="@font/montserrat_regular"
        app:fontStyle="normal"
        app:fontWeight="400" />
    <font
        android:font="@font/montserrat_italic"
        android:fontStyle="italic"
        android:fontWeight="400"
        app:font="@font/montserrat_italic"
        app:fontStyle="italic"
        app:fontWeight="400" />


</font-family>

Kotlin 用法:

val textView = dialog.findViewById<TextView>(android.R.id.message) as TextView
val typeface = ResourcesCompat.getFont(context,R.font.cc_montserrat_regular)
        textView.typeface = typeface

Android 项目截图:

编辑:这不是请求的解决方案:/

我找到了 Typeface.Builder class,我认为这就是您想要的。不幸的是,它只能从 API 26 级及以上获得。也许很快就会出现兼容库。

https://developer.android.com/reference/android/graphics/Typeface.Builder.html

 Typeface.Builder buidler = new Typeface.Builder("your_font_file.ttf");
 builder.setFontVariationSettings("'wght' 700, 'slnt' 20, 'ital' 1");
 builder.setWeight(700);  // Tell the system that this is a bold font.
 builder.setItalic(true);  // Tell the system that this is an italic style font.
 Typeface typeface = builder.build();

这里是如何在 android studio

中使用不同字体粗细的方法
  1. 打开app/src/main/res/layout/you_awesome_layout.xml
  2. Select Design tab
  3. 在组件树面板中,打开你TextView和selectView all attributes在右侧菜单的底部
  4. 在“属性”面板中,打开 fontFamily 下拉菜单和 select More Fonts…
  5. Select家庭YouFontFamilyName
  6. Select风格Regular/Bold/Semibold/Black/WhateverStyleYouHaveThere

瞧,我认为这是实现你想要的唯一方法

正如@FlorianWalther 所指出的,TextView.textFontWeight attribute is exactly what I was looking for. This attribute was apparently added in API level 28, but was not documented until recently.

确保所有权重都在同一个 XML 文件中(如我的问题),然后只需将属性与 fontFamily 属性一起使用即可。

<TextView android:id="@+id/weightedTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:fontFamily="@font/archivo_narrow"
    android:textFontWeight="700"/>

据我所知,此属性仅在 API 级别 28 及以上可用,如果我在支持库中找到它的对应项,我会更新。

第 1 步:查找或下载您的字体,比方说 cavier_dream

第 2 步:Right-click 在 res 文件夹上,并在 res 文件夹内创建字体资源文件夹

第 3 步:Right-click 在字体文件夹中创建一个字体资源文件,比方说 app_font.xml

第四步:打开app_font.xml文件,修改如下

<?xml version="1.0" encoding="utf-8"?>

<font
    android:font="@font/cavier_dream"
    android:fontWeight="400"
    android:fontStyle="normal"
    app:fontWeight="400"
    app:fontStyle="normal"
    app:font="@font/cavier_dream"/>

用法:

要在整个应用程序中全局使用,请转到 styles.xml 并在主题内部创建一个新项目,如下所示

 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:fontFamily">@font/app_font</item>
</style>

对于本地使用,只需使用 fontFamily 属性并将 app_font 设置为值。

编码愉快:)

由于 textFontWeight 属性是 API 级别 28 及更高级别,支持旧设备的解决方法是为每个字体粗细创建一个单独的 fontFamily 并从视图中引用 fontFamily。

res/layout/your_layout.xml

<TextView
    ...
    android:fontFamily="@font/fontFamily_your_font_demibold 
/>

res/font/fontFamily_your_font_demibold.xml

<font-family xmlns:app="http://schemas.android.com/apk/res-auto">

    <font
        app:font="@font/your_font_demibold"
        app:fontStyle="normal"
        app:fontWeight="600" />

</font-family>

res/font/fontFamily_your_font_bold.xml

<font-family xmlns:app="http://schemas.android.com/apk/res-auto">

    <font
        app:font="@font/your_font_bold"
        app:fontStyle="normal"
        app:fontWeight="800" />

</font-family>

我为一种字体的几种粗细而苦恼:粗体、半粗体、中等、常规。 对我来说,当我为每个权重创建一个 .xml 文件时,它终于起作用了,包括正常和斜体,然后在布局或样式中使用 android:fontFamily:fontFamily: 引用它们。后者很重要,否则它只能在非常高的 API 水平上起作用。

    <font-family xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">


    <font android:font="@font/internal_inter_bold" 
        android:fontStyle="normal"
        android:fontWeight="700"
        app:font="@font/internal_inter_bold"
        app:fontStyle="normal"
        app:fontWeight="700" />
    <font android:font="@font/internal_inter_bold_italic"
        android:fontStyle="italic"
        android:fontWeight="700"
        app:font="@font/internal_inter_bold_italic"
        app:fontStyle="italic"
        app:fontWeight="700" />
     </font-family>



     <style name="numbers_large">
        <item name="android:textSize">32sp</item>
        <item name="android:fontFamily">@font/inter_bold</item>
        <item name="fontFamily">@font/inter_bold</item>
    </style>

这甚至在 Android 5.0 中也有效,没有针对较低版本进行测试。

所以基本上为每个字体粗细创建一个 font.xml 文件,同时使用 app: 和 android: 前缀,然后用这两个前缀引用它们。

请参阅官方 Android 字体粗细值参考:

android:fontWeight

整数。字体的粗细。当字体加载到字体堆栈中并覆盖字体 header 表中的任何粗细信息时,将使用此属性。 属性值必须是正数,100 的倍数,介于 100 和 900 之间(含)。如果您未指定属性,应用程序将使用字体 header 表。最常见的值为常规字重 400 和粗体字重 700。

https://developer.android.com/guide/topics/resources/font-resource

Florian 在关于 < API 28 的评论中是正确的,只是明确说明它(因为我花了很长时间试图弄清楚它是如何工作的):

Android 似乎忽略了字体系列中的所有内容,除了字体粗细 700 和 400,它分别用于粗体和 non-bold textStyles。

就是这样。您可以使用常规 400/700 和斜体 400/700。其他定义中的 None 似乎已被使用,而且只有在较新的 API 中,您才能真正对它们进行任何操作。如果我遗漏了什么,请告诉我,但这似乎是您可以在较低 APIs 上控制的所有内容 - 粗体与否。


系统似乎确实在寻找替代权重,因此如果您指定 bold 但您没有使用权重 700 定义任何内容,它将拉另一个重量(甚至是斜体变体),但实际上你不能说“为此样式使用 Medium 500” - 你必须创建一个单独的字体系列并明确使用它,并且到那时你还不如指定实际的字体呢?


为了完整起见,我已经完成了多种字体系列的事情(我使用的每个重量都有一个单独的字体 - 常规,中等)并将它们应用到 styles 由 Material Design type scale generator。字体比例使用不同的权重,例如 light 用于 Headline1medium 用于 Subtitle2 但显然 Android 没有使用它们(而且它们也没有在样式层次结构中指定)。

所以您可以通过将字体系列参考添加到生成的样式中来解决这个问题:

<style name="TextAppearance.MdcTypographyStyles.Headline1" parent="TextAppearance.MaterialComponents.Headline1">
    <item name="fontFamily">@font/my_font_weight_light</item>
    <item name="android:fontFamily">@font/my_font_weight_light</item>
    <item name="android:textSize">123sp</item>
    <item name="android:letterSpacing">-0.0122</item>
</style>

其中 my_font_weight_light.xml 是一个仅包含 light 字体变体的字体系列

<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
    <font
        app:font="@font/my_font_light_italic"
        app:fontStyle="italic"
        app:fontWeight="400" />
    <font
        app:font="@font/my_font_light"
        app:fontStyle="normal"
        app:fontWeight="400" />
</font-family>

权重错误,400 常规 ,但我想如果 Android 只对 non-bold 文本使用 400,如果我只是给它期望的值,它就不太可能做一些奇怪的事情,所以它不必去寻找替代品(也许选择斜体)。无论如何,“重量”是由我应用于样式的字体系列定义的。我没有费心添加 bold 因为样式使用固定的权重而且我也没有使用粗体。

(edit - Jimit Patel 在评论中提到这在一种情况下对他们不起作用,并且使用粗体字体需要指定权重 700 以使其在不同的 API 之间保持一致。因此,正确的权重可能很重要 - 或者至少选择 400700 最接近它。我不能花时间测试所有这些所以我就放在那里!)


下一个有趣的事情是,如果您通过设置 fontFamily 属性通过主题将字体系列应用于整个应用程序,that will override any fontFamily settings you apply through textAppearance 因为主题样式优先于 textAppearance.因此,您的“加权”样式将失去其“重量”,因为 fontFamily 将设置回正常版本,并显示 常规 400 值。

要解决这个问题,您必须应用样式 作为样式,而不是 textAppearance,即:

style="@style/TextAppearance.MdcTypographyStyles.Headline1"

好玩!!