Недавно я столкнулся с проблемой поддельного жирного и курсивного текста при использовании семейства шрифтов в Android разработке.
В этой статье хочу рассказать об этой проблеме и о её решении.
Создание семейства шрифтов
Начиная с API 26, появилась возможность объединять шрифты в
семейства.
Семейство шрифтов это набор файлов шрифтов с указанием их стиля и
веса.
Вы можете создать новое семейство шрифтов как ресурс XML и обращаться к нему как к единому элементу, вместо того, чтобы ссылаться на каждый стиль и вес как на отдельные ресурсы.
Таким образом система сможет выбрать правильный шрифт в зависимости от стиля текста, который вы пытаетесь использовать.
Пример файла:
<?xml version="1.0" encoding="utf-8"?><font-family xmlns:android="http://personeltest.ru/away/schemas.android.com/apk/res/android"> <font android:fontStyle="normal" android:fontWeight="400" android:font="@font/lobster_regular" /> <font android:fontStyle="italic" android:fontWeight="400" android:font="@font/lobster_italic" /></font-family>
<?xml version="1.0" encoding="utf-8"?><font-family xmlns:app="http://personeltest.ru/away/schemas.android.com/apk/res-auto"> <font app:fontStyle="normal" app:fontWeight="400" app:font="@font/lobster_regular" /> <font app:fontStyle="italic" app:fontWeight="400" app:font="@font/lobster_italic" /></font-family>
Атрибут fontStyle
определяет стиль начертания
шрифта обычное(normal
) или
курсивное(italic
).
В свою очередь, fontWeight
устанавливает вес, aka
насыщенность шрифта.
И конечно, font
будет задавать шрифт который будет
использоваться при заданном fontWeight
и
fontStyle
.
Вес шрифта
Этот стандарт пришел с web-разработки. Значение устанавливается от 100 до 900 с шагом 100.
Следующая таблица соответствует распространенным именам насыщенности:
Значение | Общее название |
---|---|
100 | Тонкий (Волосяной) |
200 | Дополнительный светлый |
300 | Светлый |
400 | Нормальный |
500 | Средний |
600 | Полужирный |
700 | Жирный |
800 | Дополнительный жирный |
900 | Черный (Густой) |
В основном, в файле семейства шрифтов, достаточно указать только шрифты для нормального начертания 400, и стандартного жирного 700.
Более подробно о насыщенности шрифта читайте здесь.
Поддельный курсив
Когда система не может найти подходящий шрифт для жирного или курсивного текста, Android компенсирует это, растягивая символы для поддельного жирного и наклоняя их для поддельного курсива.
Такая проблема может возникнуть, когда в семействе шрифтов не указан шрифт для нужного стиля.
Я сделал небольшое
приложение которое показывает отличия искусственной стилизации
от настоящей на примере Lobster Two
шрифта:
Вы можете заметить, как при использовании искусственного начертания шрифта, текст получается более сплюснутым. Хуже того, затрудняется разборчивость из-за размазывания букв и неправильного наклона.
Решение
В данном примере, я создал lobster_two.xml
в
котором указал шрифты для обычного, курсива, жирного, и жирного
курсива:
<?xml version="1.0" encoding="utf-8"?><font-family xmlns:app="http://personeltest.ru/away/schemas.android.com/apk/res-auto"> <font app:fontStyle="normal" app:fontWeight="400" app:font="@font/lobster_two_normal" /> <font app:fontStyle="italic" app:fontWeight="400" app:font="@font/lobster_two_italic" /> <font app:fontStyle="normal" app:fontWeight="700" app:font="@font/lobster_two_bold" /> <font app:fontStyle="italic" app:fontWeight="700" app:font="@font/lobster_two_bold_italic" /></font-family>
А также, lobster_two_incomplete.xml
в котором
указал только шрифт для обычного текста:
<?xml version="1.0" encoding="utf-8"?><font-family xmlns:app="http://personeltest.ru/away/schemas.android.com/apk/res-auto"> <font app:fontStyle="normal" app:fontWeight="400" app:font="@font/lobster_two_normal" /></font-family>
И переключался между ними по нажатию на переключатель.
Когда использовался lobster_two_incomplete.xml
,
вместо lobster_two.xml
, то происходило искусственное
растягивание и наклонение шрифта.
Чтобы избежать этого, нужно прописывать в файле семейства шрифтов всевозможные стили, а также всегда использовать этот файл в качестве шрифта.
Использование в коде
// Правильноval typeFace = resources.getFont(R.font.lobster_two)textView.setTypeface(typeFace, Typeface.BOLD)// Не правильноtextView.typeface = resources.getFont(R.font.lobster_two_bold)// Не правильноval typeFace = resources.getFont(R.font.lobster_two_incomplete)textView.setTypeface(typeFace, Typeface.BOLD)// Не правильноval typeFace = resources.getFont(R.font.lobster_two_normal)textView.setTypeface(typeFace, Typeface.BOLD)
Используем в xml
// Правильно<TextView ... android:fontFamily="@font/lobster_two" android:textStyle="bold|italic"/>// Не правильно<TextView ... android:fontFamily="@font/lobster_two_bold_italic"/>// Не правильно<TextView ... android:fontFamily="@font/lobster_two_incomplete" android:textStyle="bold|italic"/>// Правильно<TextView ... android:fontFamily="@font/lobster_two" android:textStyle="bold"/>// Не правильно<TextView ... android:fontFamily="@font/lobster_two_bold"/>// Не правильно<TextView ... android:fontFamily="@font/lobster_two_normal" android:textStyle="bold"/>