Typeface — це клас Android SDK з пакета android.graphics, який представляє накреслення шрифту і використовується для кастомізації тексту в TextView та інших компонентах інтерфейсу. Typeface визначає родину шрифту, його вагу (normal, bold) та стиль (normal, italic). За даними Google Developers, Typeface підтримує завантаження з файлів TTF, OTF, XML-шрифтів та системних ресурсів. Це центральний клас для керування типографікою в Android-додатках.
Головне
Typeface — це клас Android, який інкапсулює інформацію про шрифт: його родину (Roboto, Arial, Serif) та модифікатори стилю (bold, italic). На відміну від UIFont в iOS, Typeface не містить інформації про розмір — розмір тексту задається окремо через властивість textSize в TextView або TextStyle в Spannable. Typeface відповідає лише за накреслення та гарнітуру шрифту.
Клас доступний на всіх рівнях API. До Android 4.4 Typeface підтримував лише обмежений набір системних шрифтів: DEFAULT, DEFAULT_BOLD, MONOSPACE, SERIF, SANS_SERIF. Починаючи з Android 8.0 (API 26), було додано підтримку завантаження кастомних шрифтів через XML-ресурси, а Android 10 додав підтримку варіативних шрифтів.
Android надає кілька вбудованих екземплярів Typeface: Typeface.DEFAULT — системний шрифт Roboto (Material) або Noto (AOSP), DEFAULT_BOLD — жирна версія, MONOSPACE — моноширинний шрифт для коду, SERIF — шрифт з засічками (Noto Serif), SANS_SERIF — гротеск (Noto Sans). Ці константи доступні без контексту та не потребують дозволів на читання файлів.
Система Android використовує Typeface для відображення всього тексту, включаючи системний інтерфейс, заголовки, підписи та сповіщення. Кожен додаток може перевизначити типовий шрифт через тему (android:fontFamily) або програмно через setTypeface(). Typeface застосовується до всіх компонентів, успадкованих від TextView: кнопок, EditText та кастомних вюхів.
Android 8.0+ дозволяє додавати шрифти в res/font та використовувати їх через XML-ресурси. Файл шрифту (TTF або OTF) поміщується в res/font, після чого створюється посилання R.font.font_name. Typeface завантажується через ResourcesCompat.getFont(context, R.font.font_name). Цей спосіб кращий, оскільки шрифт компілюється в APK та підтримує системи збірки ProGuard.
Ресурсний спосіб також підтримує родини шрифтів через XML-файл в res/font: можна вказати кілька файлів для різних накреслень (regular, bold, italic) і система автоматично вибере потрібний файл при виклику setTypeface. Це спрощує типографіку — достатньо задати fontFamily в темі, і Android сам підбере підходячий файл.
Метод Typeface.create(Typeface family, int style) створює екземпляр шрифту із зазначеною родиною та стилем. Якщо родина вже має запитаний стиль, повертається існуючий екземпляр. Якщо стиль відсутній, Android синтезує його — застосовує псевдожирність або штучний курсив до базового шрифту.
val boldTypeface = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)
val italicTypeface = Typeface.create(Typeface.MONOSPACE, Typeface.ITALIC)
val customTypeface = ResourcesCompat.getFont(context, R.font.montserrat_regular)
textView.typeface = boldTypeface
Синтезований псевдожирний може виглядати неякісно на тонких шрифтах. Для кращого результату використовуйте файл шрифту з справжнім bold-накресленням. Typeface.create() з неіснуючим стилем не викидає виняток, а повертає найближчий доступний варіант.
Для завантаження Typeface з assets використовуйте Typeface.createFromAsset(assetManager, path). Шрифт поміщується в каталог src/main/assets/fonts/, а шлях вказується відносно assets. Цей спосіб працює на всіх версіях Android, але не підтримує родини шрифтів і вимагає вказівки конкретного файлу для кожного накреслення.
Метод Typeface.createFromFile(File) завантажує шрифт з довільного файлу в файловій системі. Це корисно для шрифтів, завантажених з мережі або скопійованих у внутрішнє сховище додатка. createFromFile також не потребує контексту, що зручно для фонових завдань, але файл повинен бути доступним для читання.
Багаторазове завантаження Typeface з assets через createFromAsset може призводити до створення дублікативних об’єктів. Кожен виклик createFromAsset завантажує файл заново. Рекомендується реалізувати кеш Typeface через HashMap, де ключем є шлях до файлу, а значенням — завантажений екземпляр. Це особливо актуально для списків з різними типами шрифтів.
object TypefaceCache {
private val cache = mutableMapOf<String, Typeface>()
fun getTypeface(context: Context, filename: String): Typeface {
return cache.getOrPut(filename) {
Typeface.createFromAsset(context.assets, "fonts/$filename")
}
}
}
// Usage
val typeface = TypefaceCache.getTypeface(context, "Roboto-Bold.ttf")
Кеш у пам’яті гарантує, що один шрифт завантажується тільки один раз за сесію додатка. При зміні конфігурації (поворот екрану) кеш зберігається, оскільки знаходиться в об’єкті companion. Для очищення кешу при нестачі пам’яті використовуйте WeakHashMap або прослуховуйте onTrimMemory.
Typeface застосовується до TextView через метод setTypeface(Typeface tf) або setTypeface(Typeface tf, int style). Другий варіант дозволяє змінити стиль (bold/italic) відносно поточного шрифту. В XML використовується атрибут android:fontFamily з посиланням на шрифт або системну родину. Для програмного встановлення виклик setTypeface(monospaceTypeface) замінить шрифт на вказаний.
Typeface впливає на весь текст TextView. Якщо потрібен різний шрифт в одному рядку, використовуйте SpannableString з TypefaceSpan. TypefaceSpan приймає Typeface або родину і застосовується до діапазону символів. Це єдиний спосіб змішувати шрифти в межах одного TextView без вкладених компонентів.
Застосуйте TypefaceSpan лише до частини рядка. Наприклад, значення змінної в тексті повинно бути моноширинним, а решта тексту — системним шрифтом. Створіть SpannableString та встановіть TypefaceSpan з MONOSPACE Typeface на потрібний діапазон. Решта тексту зберігає оригінальний шрифт TextView.
val text = "Code: variableName"
val spannable = SpannableString(text)
spannable.setSpan(
TypefaceSpan(Typeface.MONOSPACE),
5, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
spannable.setSpan(
ForegroundColorSpan(Color.BLUE),
5, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
textView.text = spannable
Текст «variableName» відобразиться моноширинним шрифтом синього кольору, а слово «Code:» залишиться системним шрифтом. TypefaceSpan можна комбінувати з будь-якими іншими спанами для точного контролю над кожною ділянкою тексту.
Android підтримує кілька форматів шрифтів: TrueType (TTF), OpenType (OTF) та Web Open Font Format (WOFF2) починаючи з Android 10. TTF і OTF — основні формати для кастомних шрифтів. XML-шрифти (Font Family) не є окремим форматом, а слугують описом того, який файл використовувати для кожного накреслення.
Для використання кастомного шрифту через res/font створіть XML-файл родини, де вказуються шляхи до файлів шрифтів для regular, bold та italic. Потім у темі додатка вкажіть android:fontFamily="@font/custom_family". Усі екземпляри TextView, які використовують цю тему, автоматично отримають правильне накреслення для кожного стилю.
Якщо шрифт завантажується з мережі, збережіть його в filesDir або cacheDir та завантажте через Typeface.createFromFile. Після завантаження оновіть Typeface в TextView. Для асинхронного завантаження використовуйте coroutine або DownloadManager, а після завершення постьте в UI-потік через Handler. Це типовий сценарій для додатків з кастомною типографікою, що завантажується на вимогу.
// Save font file to internal storage
val fontFile = File(context.cacheDir, "downloaded-font.otf")
fontFile.outputStream().use { output ->
// inputStream from network
inputStream.copyTo(output)
}
// Create Typeface from file
val downloadedTypeface = Typeface.createFromFile(fontFile)
textView.typeface = downloadedTypeface
Перед завантаженням перевірте доступність файлу: якщо файл пошкоджений або недійсний, Typeface.createFromFile викидає RuntimeException. Рекомендується обертати виклик в try-catch і у разі помилки повертатися до типового системного шрифту.
В Jetpack Compose Typeface Android SDK не використовується безпосередньо. Натомість Compose надає FontFamily та FontWeight для типографіки. FontFamily завантажується через Font.Resource та Font.File. Система типографіки Compose визначається через MaterialTheme.typography, де кожному стилю (h1, body1, button) можна призначити кастомну FontFamily.
Для завантаження шрифту з ресурсів Compose використовує Font(R.font.font_name, weight, style). Шрифт з assets завантажується через Font(assetPath = "fonts/custom.otf", weight, style). Після визначення шрифту він передається в Typography, а потім застосовується через MaterialTheme.typography.bodyLarge та аналогічні стилі.
Якщо є готовий Typeface, створений через Android SDK, його можна використати в Compose через TypefaceAdapter або створивши FontFamily на основі Typeface. Отримайте Typeface з Typeface.create та передайте його в FontFamily.Custom(listOf(Font(typeface))). Однак рекомендується використовувати рідний підхід з Font.Resource, оскільки він краще оптимізований для Compose.
Завантаження шрифтів з файлів — потенційно дорога операція. Кожен виклик Typeface.createFromAsset або Typeface.createFromFile читає файл з диска, парсить його та створює об’єкт Typeface. Для шрифтів розміром 1-2 МБ це займає 10-50 мс на холодному запуску. Кешування Typeface — обов’язкова практика для додатків з кастомними шрифтами.
Android SDK не кешує шрифти, створені через createFromAsset або createFromFile. На відміну від системних шрифтів, які попередньо завантажуються в процесі Zygote, кастомні шрифти завантажуються при кожному зверненні. Рекомендується використовувати LruCache або ConcurrentHashMap з ідентифікатором шрифту як ключем. Розмір кешу 10-20 екземплярів покриває типовий набір шрифтів додатка.
Android 8.0+ оптимізує завантаження шрифтів через XML Font Family. При вказівці android:fontFamily="@font/my_family" в XML-розмітці Android завантажує шрифт леніво — лише коли компонент стає видимим. Система також кешує шрифти, завантажені через ResourcesCompat.getFont(), у глобальному кеші процесів. Це робить ресурсний спосіб найбільш продуктивним.
При використанні Typeface в адаптерах RecyclerView важливо не завантажувати шрифт в методі onBindViewHolder. Викличіть завантаження один раз при створенні адаптера або використовуйте ViewHolder з попередньо завантаженим Typeface. Якщо кожен елемент списку потребує унікальний шрифт, реалізуйте кеш через WeakHashMap та очищайте його при прокрутці поза межі видимих позицій для економії пам’яті.
Часто задавані питання
Typeface — це конкретний екземпляр шрифту для програмного використання. FontFamily — XML-ресурс, що описує групу файлів шрифту для різних накреслень (regular, bold, italic). В runtime FontFamily перетворюється в Typeface через ResourcesCompat.getFont. Typeface можна створити безпосередньо з файлу, минаючи FontFamily.
Використовуйте Typeface.createFromFile(File) або Typeface.DEFAULT. Ці методи не потребують контексту, оскільки працюють з файловою системою або вбудованими константами. Для завантаження з assets або ресурсів контекст обов’язковий, оскільки потрібен доступ до AssetManager та ресурсів додатка.
Ні, WebView використовує CSS-властивість font-family для вказівки шрифтів. Щоб використати кастомний шрифт в WebView, помістіть файл шрифту в assets та вкажіть його через @font-face в CSS. Typeface Android SDK працює лише з нативними UI-компонентами (TextView та його нащадками).
Так, починаючи з Android 10 (API 29). Варіативні шрифти завантажуються через ResourcesCompat.getFont або Typeface.createFromFile. Для налаштування осей варіативності (weight, width) використовуйте FontStyle в Compose або XML-атрибути. Програмна зміна осей можлива лише через низькорівневі API Skia.
Найчастіші причини: файл шрифту відсутній в проекті, неправильне ім’я файлу, шрифт пошкоджений або використовується синтезований стиль, якого немає в файлі. Перевірте, що файл додано в res/font або assets, і що його ім’я вказано без розширення у разі ресурсного способу.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також