Как использовать указанные веса для шрифтов в XML

Использование шрифтов в 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 (макет/стиль), либо в коде Java. Для TextView отсутствует атрибут fontWeight, а Typeface, созданный из ResourcesCompat.getFont(context, R.font.archivo_narrow) не упоминает вес шрифта.

Я понимаю, что могу просто указать конкретный ресурс шрифта (например, R.font.archivo_narrow_semibold), но тогда какой смысл иметь атрибут fontWeight в font-family?


Обновлять

Новый статический create(Typeface family, int weight, boolean italic) был добавлен в API уровня 28 вместе с getWeight() метод экземпляра. Это, наконец, позволяет использовать атрибут fontWeight в коде Java; правда только для API Level 28 и выше, аналогов в библиотеке поддержки я не нашел.

Это полезно и показывает, что атрибут fontWeight в прошлом не служил никакой цели, но мне бы очень хотелось иметь возможность использовать вес в стилях XML.


person Bryan    schedule 05.10.2017    source источник
comment
Я вижу обновление в вопросе, но я думаю, что на самом деле это должен быть ответ, поскольку он дает гораздо лучший ответ на реальный вопрос, чем любой из текущих ответов.   -  person arekolek    schedule 20.12.2018
comment
Ниже 28 вес шрифта служит для того, чтобы различать обычный и жирный шрифт.   -  person Florian Walther    schedule 14.04.2019
comment
Вы пробовали XML-атрибут textFontWeight? У меня не работает даже на API 28.   -  person Florian Walther    schedule 14.04.2019


Ответы (9)


Это похоже на то, что Android следует веб-стандартам для управления шрифтами и их размеров для приложений Android.

Свойство «font-weight» используется для определения веса шрифта, например обычного или полужирного.

Но для всех других весов используется числовой диапазон от 100 до 900. Одна из проблем с веб-шрифтами заключается в том, что большинство веб-браузеров не поддерживают должным образом начертания шрифта, кроме обычного и полужирного. В следующей таблице описаны возможные сопоставления весов с числовыми определениями:

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

Вы можете узнать больше о толщине шрифта здесь


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>

Использование Котлина:

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-проекта:

введите описание изображения здесь

person Rajesh Dalsaniya    schedule 12.10.2017
comment
Да, но как мне использовать различную толщину шрифта? - person Bryan; 13.10.2017
comment
Не взвешивать, чтобы идентифицировать шрифты по отдельности? Можете ли вы привести пример, что вас смущает? - person Rajesh Dalsaniya; 15.10.2017
comment
Я могу указать атрибут font-weight в теге <font>, но я не могу найти способ сослаться на этот атрибут font-weight где-либо еще в моем коде (т. е. я могу установить вес, я просто не могу использовать вес). Существует атрибут textStyle, но вы можете только укажите bold, italic или bold|italic. Нет semibold например. - person Bryan; 16.10.2017
comment
@Bryan Я думаю, что вес шрифта предназначен для внутренней справки, только вам не нужно определять его в коде. В качестве примера того, что вы хотите использовать шрифт в программировании, вы можете получить его с помощью R.font.fontname_type. - person Rajesh Dalsaniya; 16.10.2017
comment
@Bryan Я использую шрифт в своем проекте таким образом. 1. Я определил xml, как вы сделали выше, а затем в коде val typeface = ResourcesCompat.getFont(context,R.font.cc_montserrat_regular) textView.typeface = typeface - person Rajesh Dalsaniya; 16.10.2017
comment
Тогда зачем вообще атрибут font-weight? Что он делает внутри? Это кажется бесполезным, если у меня нет возможности сослаться на него. - person Bryan; 16.10.2017
comment
@Bryan Проверьте обновленный ответ. Как я использую шрифты в своем проекте. - person Rajesh Dalsaniya; 16.10.2017
comment
@Bryan, вам нужно создать отдельный XML для каждого типа шрифта полужирный, обычный, жирный и т. д. - person Rajesh Dalsaniya; 16.10.2017
comment
Это только кажется излишеством. font-family обычно охватывает все варианты, а не только normal и italic варианты определенного веса. И это по-прежнему не объясняет, почему существует атрибут font-weight, который я не могу использовать. - person Bryan; 16.10.2017
comment
@Bryan, я потратил часы, пытаясь найти ответ на этот очень простой вопрос. Не уверен, почему все продолжают предлагать нелепые обходные пути. Вы когда-нибудь находили решение? - person Theo; 19.12.2017
comment
@Theo Нет, похоже, использование отдельных ресурсов шрифтов - единственное решение на данный момент. Однако я слежу за любыми изменениями в API, я обновлю, если что-нибудь найду. - person Bryan; 19.12.2017
comment
@Theo Кто-нибудь проверял этот документ со шрифтами для Android? developer.android.com/guide/ темы/пользовательский интерфейс/внешний вид/ - person Rajesh Dalsaniya; 20.12.2017
comment
@RajeshDalsaniya Я сослался на этот документ в своем первоначальном вопросе. Здесь снова показано, как указать атрибут font-weight, но для используйте шрифт, необходимый для получения Typeface экземпляр; который не имеет никакой ссылки на атрибут font-weight. - person Bryan; 20.12.2017
comment
Насколько я понимаю, ниже API 28 это различает только обычный и жирный шрифт. - person Florian Walther; 14.04.2019
comment
Безумно, что для этого до сих пор нет хорошего совместимого решения, безумно, что эта ужасная перефразировка вопроса, опубликованного как ответ, получила более 50 голосов. - person Nick Cardoso; 19.01.2021

Как указал @FlorianWalther, атрибут TextView.textFontWeight именно то, что я искал. Этот атрибут, по-видимому, был добавлен на уровне API 28, но до недавнего времени не был задокументирован.

Убедитесь, что все веса находятся в одном файле 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 и выше, я обновлю его, если найду его аналог в библиотеке поддержки.

person Bryan    schedule 15.04.2019
comment
Проблема, связанная с бэкпортом textFontWeight: issuetracker.google.com/issues/145311058 - person Gaëtan; 29.04.2020
comment
Связанная проблема на самом деле содержит ссылки на реализацию этого для более старых версий Android. - person user3738870; 03.05.2020

Флориан прав в комментариях по поводу ‹ API 28, и просто чтобы быть откровенным об этом (поскольку я потратил целую вечность, пытаясь понять, как это работает):

Похоже, что Android игнорирует все элементы семейства шрифтов, кроме шрифтов с начертанием 700 и 400, которые используются для полужирных и нежирных textStyle соответственно.

Вот и все. У вас может быть обычный 400/700 и курсив 400/700. Ни одно из других определений, кажется, не используется, и только с более новыми API вы действительно можете что-то с ними делать. Если я что-то упустил, дайте мне знать, но это, похоже, все, что вы можете контролировать в более низких API - жирный или нет.


Похоже, что система возится с поиском альтернативного веса, поэтому, если вы укажете bold, но у вас ничего не определено с весом 700, он вытянет другой вес (даже вариант, выделенный курсивом), но вы на самом деле нельзя сказать использовать Medium 500 для этого стиля - вам нужно создать отдельное семейство шрифтов и явно использовать его, и в этот момент вы могли бы просто указать фактический шрифт вместо этого?


Для полноты картины я сделал несколько семейств шрифтов (отдельный для каждого веса, который я использую — обычный, средний и т. д.) и применил их к style, сгенерированным Генератор масштаба типа Material Design. Шкала шрифтов использует разные веса, например легкий для Заголовок1 и средний для Подзаголовок2, но, очевидно, 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 – это семейство шрифтов, в которое входит только облегченный вариант шрифта.

<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 в любом случае использует только 400 для нежирного текста, меньше шансов, что он сделает что-то странное, если я просто дам ему ожидаемое значение, поэтому ему не нужно искать альтернативу (и, возможно, выбирать курсив). В любом случае вес определяется тем, какое семейство шрифтов я применяю к стилю. Я не стал добавлять полужирный, поскольку стили используют фиксированный вес, а я все равно не использую полужирный шрифт.

(редактировать — Джимит Патель упоминает в комментариях, что это не сработало для них в одном случае, и использование полужирного шрифта требовало указания веса 700, чтобы добиться согласованности. в разных API. Так что, возможно, важен правильный вес или, по крайней мере, выбор того из 400 или 700, который ближе всего к нему. Я не могу тратить время на тестирование всего этого так что просто выкладываю!)


Следующая интересная вещь: если вы применяете семейство шрифтов ко всему приложению через свою тему, устанавливая атрибуты fontFamily, , который переопределит любые fontFamily настройки, которые вы применяете через textAppearance, поскольку стили темы имеют приоритет над textAppearance. Таким образом, ваши взвешенные стили потеряют свой вес, потому что fontFamily вернется к обычной версии с присутствующим обычным значением 400.

Чтобы обойти это, вы должны применить свой стиль как стиль, а не textAppearance, то есть:

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

весело!!

person cactustictacs    schedule 03.10.2020
comment
Красиво сформулировано. У меня есть еще одно наблюдение, чтобы добавить. Если я использую fontWeight="400" в файле полужирного шрифта TTF, он ведет себя странно в разных версиях Android API, а если я использую fontWeight="700", то он работает точно так, как ожидалось. - person Jimit Patel; 04.12.2020
comment
Это с textStyle (когда вы на самом деле используете шрифт, например, когда вы настраиваете TextView) установлено на normal или bold? Если это bold, то я ожидаю этого, поскольку это в основном говорит о том, что ищите вес 700, и если у вас нет определенного в вашем шрифте, это может стать странным. Этот хакерский подход в основном создает новый шрифт для каждого веса и обрабатывает их все как regular для textStyle - поэтому, если вы хотите полужирный шрифт, вам нужно использовать любой шрифт со средним/полужирным/жирным вариантом. - person cactustictacs; 04.12.2020
comment
Если это все еще странно даже с regular или normal или любым другим значением textStyle, дайте мне знать, и я добавлю примечание в ответ! - person cactustictacs; 04.12.2020
comment
Нигде не использовались специальные атрибуты для выделения жирным шрифтом. Я использую жирный шрифт, чтобы все соответствовало бренду, но это было обнаружено при тестировании одного и того же TextView на разных устройствах. Вы можете протестировать его для API от 21 до 29, для меня 21, 22 и 29 работали нормально, все остальное выделялось жирным шрифтом. Проверьте 2 или 3 разных TTF для получения более точных наблюдений. - person Jimit Patel; 11.12.2020
comment
Хм, хорошо, я сам этого не видел (в основном смотрел на API 24, 29 и 30), но, может быть, я просто не заметил, или это тоже может зависеть от шрифта или версии библиотеки поддержки... Я буду просто добавьте примечание, чтобы люди проверили, работает ли это, и попробуйте разные веса, если это не так, моя идея 400 в любом случае была всего лишь предположением. Спасибо! - person cactustictacs; 11.12.2020

Поскольку атрибут textFontWeight имеет уровень API 28 и выше, обходным путем для поддержки старых устройств является создание отдельного семейства шрифтов для каждого веса шрифта и ссылка на семейство шрифтов из представления.

res/layout/your_layout.xml

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

res/шрифт/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/шрифт/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>
person Marius Kohmann    schedule 02.12.2019
comment
семейство шрифтов в этом случае бесполезно, и лучше использовать шрифт непосредственно в текстовом представлении. - person Magnas; 15.01.2020

Я боролся с несколькими весами шрифта: жирным, полужирным, средним, обычным. Для меня это, наконец, сработало, когда я создал файл .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:, а затем ссылайтесь на них с обоими префиксами.

person Peterdk    schedule 30.04.2020

Редактировать: это не решение запроса:/

Я нашел класс Typeface.Builder, который, как мне кажется, вам нужен. К сожалению, он доступен только с уровня 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();
person kassim    schedule 22.02.2018
comment
Нет, к сожалению, установить вес можно только через Typeface.Builder; по-прежнему нет способа сослаться на этот вес через созданный Typeface. - person Bryan; 23.02.2018
comment
Да, извините, я нашел ввод веса и погорячился, не разобравшись до конца. - Я нашел ваш StackOverflow, пытаясь понять то же самое сам. После просмотра исходного кода все, что я могу найти, это то, что если вы обратитесь к семейству шрифтов, оно будет изо всех сил стараться получить ближайший вес к полужирному (700), если вы укажете это как стиль текста, в противном случае он найдет ближайший к 400 , Невозможно запросить желаемый вес. Надеюсь, они добавят его в ближайшее время, я использовал полужирный шрифт в качестве веса заголовка в большинстве дизайнов, и было бы очень полезно иметь ввод веса. - person kassim; 27.02.2018

вот как вы можете использовать разные веса шрифта в студии Android

  1. Открыть app/src/main/res/layout/you_awesome_layout.xml
  2. Выберите Design tab
  3. На панели «Дерево компонентов» откройте TextView и выберите View all attributes в нижней части правого меню.
  4. На панели «Атрибуты» откройте раскрывающийся список fontFamily и выберите More Fonts….
  5. Выберите семью YouFontFamilyName
  6. Выберите стиль Regular/Bold/Semibold/Black/WhateverStyleYouHaveThere

Вуаля, я думаю, это единственный способ добиться желаемого

person Wackaloon    schedule 19.06.2018
comment
Я не могу сделать так, чтобы в моих пользовательских шрифтах отображалось более двух стилей (например, отображаются только Bold и Bold Italic). Для доступных шрифтов Google (под заголовком Downloadable) стилей может быть больше; например, Advent Pro имеет тонкие, сверхлегкие, легкие, обычные, средние, полужирные и полужирные шрифты. Любая идея о том, как я могу имитировать эту функциональность с моими пользовательскими шрифтами? - person Bryan; 27.09.2018

См. официальный справочник по Android для значений веса шрифта:

Android:fontWeight

Целое. Вес шрифта. Этот атрибут используется, когда шрифт загружается в стек шрифтов, и переопределяет любую информацию о весе в таблицах заголовков шрифта. Значение атрибута должно быть положительным числом, кратным 100 и лежащим в диапазоне от 100 до 900 включительно. Если атрибут не указан, приложение использует значение из таблиц заголовков шрифта. Наиболее распространенными значениями являются 400 для обычного веса и 700 для жирного шрифта.

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

person Jacob N.    schedule 22.09.2020

Шаг 1: Найдите или загрузите свой шрифт, скажем, cavier_dream

Шаг 2: Щелкните правой кнопкой мыши папку res и создайте папку ресурсов шрифта внутри папки res.

Шаг 3: Щелкните правой кнопкой мыши папку шрифта и создайте файл ресурсов шрифта, скажем, app_font.xml.

Шаг 4: Откройте файл 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.

Удачного кодирования :)

person Minion    schedule 17.06.2019
comment
Это действительно работает, но я думаю, что это может ввести в заблуждение, поскольку вам нужно установить fontFamily, когда вы действительно хотите установить fontStyle/fontWeight. - person Marius Kohmann; 29.11.2019