Custom Font — е файл с шрифт (TTF, OTF, WOFF2), който разработчикът добавя в мобилното приложение, за да замени системния шрифт по подразбиране. Персонализираните шрифтове се използват за създаване на уникален визуален стил, съответствие с брандбука и подобряване на четливостта на различни езици. Според данните на Apple Fonts, персонализираните шрифтове се поддържат на всички платформи на Apple, а Android предоставя механизма Font Family за опростяване на зареждането. Правилното свързване на шрифта критично влияе върху типографията и цялостното възприемане на приложението.
Основни точки
Custom Font (персонализиран шрифт) — е файл с шрифт, който не е част от стандартния набор шрифтове на операционната система. Разработчиците добавят такива шрифтове в проекта за уникална типография, съответстваща на бранда. Персонализираните шрифтове могат да бъдат както платени търговски шрифтове, така и безплатни шрифтове с отворен код, например Inter, Montserrat, Roboto (персонализирана версия).
Типични сценарии за използване на персонализирани шрифтове: лога и заглавия на брандирани приложения, приложения за четене със специални типографски изисквания, игри с тематични шрифтове, приложения за нелатински езици, където системният шрифт не поддържа необходимите глифове. Според данните на Google Fonts, над 60% от приложенията в топ 100 персонализират шрифтовете за визуална диференциация.
Системните шрифтове (San Francisco на iOS, Roboto на Android) са оптимизирани за интерфейси, но не са подходящи за бранд типография. Персонализираният шрифт усилва разпознаваемостта на бранда, може да съдържа специални символи (иконични шрифтове) и подобрява четливостта за специфични аудитории. Прекомерната употреба на различни шрифтове обаче влошава UX — препоръчват се не повече от 2-3 семейства на приложение.
Мобилните платформи поддържат няколко формата на шрифтове. TrueType (TTF) — най-разпространеният формат, съвместим с всички версии на iOS и Android. OpenType (OTF) — разширение на TTF с поддръжка на лигатури, алтернативни глифове и OpenType функции. И двата формата имат разширения .ttf и .otf и работят идентично на мобилни платформи.
WOFF2 (Web Open Font Format 2) — компресиран формат за уеб, поддържан в Android от версия 10. WOFF2 осигурява компресия от 30-50% спрямо TTF. За iOS WOFF2 се поддържа чрез Safari, но в нативни приложения се изисква конвертиране в TTF/OTF. Variable Fonts (вариативни шрифтове) — модерен формат, който съхранява всички стилове в един файл.
| Формат | iOS | Android | Компресия | Характеристики |
|---|---|---|---|---|
| TTF | Да | Да | Не | Стандартен формат, широка съвместимост |
| OTF | Да | Да | Не | OpenType функции, лигатури, алтернативни глифове |
| WOFF2 | Чрез Safari | API 29+ | 30-50% | Компресиран, за спестяване на размер на APK |
| Variable | iOS 11+ | API 29+ | Висока | Един файл за всички стилове |
За мобилна разработка се препоръчва използването на OTF като основен формат — поддържа OpenType функции при същия размер като TTF. За спестяване на място в APK използвайте компресия чрез woff2 или зареждане на шрифтове при поискване.
Процесът на свързване на персонализиран шрифт в iOS се състои от две стъпки: добавяне на файла в bundle на проекта и регистрация в Info.plist. Файлът с шрифта се поставя в директорията на проекта (обикновено Resources/Fonts) и се включва в target. В Info.plist се добавя масив UIAppFonts (Fonts provided by application) с имената на файловете с шрифтове, включително разширението.
След регистрация шрифтът е достъпен чрез UIFont(name:size:) под PostScript името. PostScript името може да се разбере чрез UIFont.familyNames и UIFont.fontNames(forFamilyName:). Ако името е неправилно, UIFont(name:size:) връща nil. За отстраняване на грешки се препоръчва показване на всички регистрирани шрифтове на екрана при първото стартиране.
Нека разгледаме пълния цикъл на свързване на шрифта Montserrat в iOS проект на Swift. Файлът Montserrat-Regular.ttf се добавя към проекта, посочва се в Info.plist, след което се зарежда чрез UIFont и се прилага към UILabel. За всеки стил (regular, bold, italic) се добавя отделен файл и отделен запис в Info.plist.
// 1. В Info.plist: UIAppFonts → "Montserrat-Regular.ttf"
// 2. Заредете шрифта в кода
guard let customFont = UIFont(name: "Montserrat-Regular", size: 16) else {
// връщане към системния шрифт
label.font = UIFont.systemFont(ofSize: 16)
return
}
label.font = customFont
// 3. Използвайте в NSAttributedString
let attributes = [NSAttributedString.Key.font: customFont]
let attributed = NSAttributedString(string: "Text", attributes: attributes)
Обработката на ситуацията, когато шрифтът не е зареден (UIFont връща nil), е задължителна. Вместо срив на приложението използвайте системния шрифт като fallback. Това е особено важно за шрифтове, зареждани от мрежата или добавяни към опционални модули.
За шрифтове, изтегляни при поискване, се използва CTFontManagerRegisterGraphicsFont. Този метод регистрира шрифт от данни в паметта (Data) и го прави достъпен за UIFont. След употреба шрифтът може да бъде дерегистриран чрез CTFontManagerUnregisterGraphicsFont. Динамичното зареждане е полезно за приложения с голям набор от шрифтове, където не всички са необходими наведнъж.
В Android персонализираните шрифтове се добавят чрез ресурсната система res/font. Файловете TTF или OTF се поставят в res/font/, след което се създават XML ресурси Font Family за групиране на стилове. От Android 8.0 (API 26) нататък това е единственият препоръчителен начин. За по-стари версии се използват assets и Typeface.createFromAsset.
XML Font Family описва съответствието между стил (regular, bold, italic) и файла с шрифт. В XML маркирането атрибутът android:fontFamily="@font/my_font" автоматично избира подходящия файл при setTypeface със съответния стил. Това опростява типографията — достатъчно е да посочите семейството в темата, а Android сам ще избере bold при извикване на setTypeface(textView, Typeface.BOLD).
Създайте XML файл в res/font/my_font.xml, където са изброени всички файлове с шрифтове за различни стилове. Всеки елемент има атрибути fontStyle (normal/italic) и fontWeight (100-900). След това в маркирането посочете android:fontFamily="@font/my_font". При използване на textStyle="bold" Android автоматично ще избере файла с fontWeight 700.
<!-- res/font/my_font.xml -->
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
<font
android:fontStyle="normal"
android:fontWeight="400"
app:font="@font/my_font_regular" />
<font
android:fontStyle="normal"
android:fontWeight="700"
app:font="@font/my_font_bold" />
</font-family>
При използване на Font Family ресурсният начин автоматично кешира шрифтовете и избира правилния стил. Ако необходимото тегло липсва в семейството, Android го синтезира от най-близкото налично. За точен контрол върху шрифта използвайте Typeface.create() с изрично посочване на файла.
В междуплатформените рамки свързването на шрифтове е унифицирано. Flutter използва pubspec.yaml за посочване на шрифтове: файловете се поставят в папката fonts/ на проекта, след което се декларират в секцията fonts с посочване на семейство и стилове. След това шрифтът се прилага чрез TextStyle(fontFamily: 'Montserrat') или в темата на приложението. Flutter поддържа TTF и OTF.
React Native използва два подхода: нативен (чрез Info.plist и res/font) или чрез библиотеките react-native-vector-icons и @expo-google-fonts. Expo опростява процеса — шрифтовете се зареждат чрез expo-font: Font.loadAsync({ 'Montserrat': require('./assets/fonts/Montserrat.ttf') }). React Navigation и темите позволяват глобално задаване на шрифта.
Декларация на шрифтове в pubspec.yaml и прилагане в темата на MaterialApp. Файловете Montserrat-Regular.ttf и Montserrat-Bold.ttf се поставят в fonts/. След декларацията шрифтът е достъпен чрез TextStyle в цялото приложение. Flutter автоматично използва bold файла при fontWeight: FontWeight.bold.
// pubspec.yaml
flutter:
fonts:
- family: Montserrat
fonts:
- asset: fonts/Montserrat-Regular.ttf
- asset: fonts/Montserrat-Bold.ttf
weight: 700
// Употреба в темата
MaterialApp(
theme: ThemeData(
textTheme: TextTheme(
headlineLarge: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.bold,
fontSize: 28
)
)
)
)
Ако Flutter не намери шрифта на посочения път, приложението използва системния резервен шрифт без грешки. За отстраняване на грешки включете checkConsistency в MaterialApp — той проверява наличието на шрифтове и показва предупреждения в конзолата при липса.
Размерът на APK и IPA пряко зависи от броя на включените шрифтове. Един TTF файл тежи 50-500 KB за латински набор от знаци и до 2-5 MB за шрифтове с поддръжка на кирилица, китайски йероглифи или други разширени набори. Десет шрифта могат да добавят 10-20 MB към размера на приложението, което е критично за мобилно изтегляне.
За оптимизация използвайте subsetting — премахване на неизползвани знаци от файла с шрифта. Инструменти като glyphhanger, fonttools (pyftsubset) и Google Webfont Optimizer създават версия на шрифта само с необходимите глифове (латиница + кирилица + цифри + препинателни знаци). Това намалява размера с 50-80%. На iOS могат да се използват ресурси при поискване за шрифтове, които не са необходими при първото стартиране.
Variable Font (вариативен шрифт) — един файл, съдържащ всички стилове: от Thin до Black и от Condensed до Expanded. Един вариативен шрифт може да замени 10-20 отделни файла с различни тегла. Размерът на такъв файл е приблизително равен на 1-2 статични файла. Поддръжка: iOS 11+, Android 10+, Flutter (чрез FontVariation), React Native (чрез персонализирани библиотеки).
Използвайте WOFF2 за намаляване на размера на шрифтовете с 30-50%. На Android с API 29 можете да използвате WOFF2 директно. За iOS се изисква конвертиране на WOFF2 в TTF преди регистрация. Шрифтовете, използвани само в onboarding или на определени екрани, зареждайте чрез ресурси при поискване (iOS) или Dynamic Feature (Android) — те няма да попаднат в базовия APK.
Персонализираните шрифтове влияят на производителността по два начина: време за зареждане и памет. При първото обръщение към шрифта системата чете файла от диска, парсира таблиците на шрифта и създава вътрешни структури за рендериране. За шрифт с размер 1 MB това отнема 20-50 ms. Кеширането след първото зареждане премахва закъснението при повторни обръщения.
Памет: всеки зареден шрифт се съхранява в кеша на процеса. Системните шрифтове са предварително заредени, персонализираните се зареждат при първа употреба. В паметта шрифтът заема приблизително 2-3 пъти повече, отколкото на диска, поради разградените структури: таблици cmap, glyf, head, hmtx. За 5 персонализирани шрифта със среден размер (общ обем 3 MB) са необходими около 6-9 MB RAM.
Ограничете броя на персонализираните шрифтове до 2-3 семейства на приложение. Използвайте вариативни шрифтове за замяна на няколко стила. Прилагайте системни шрифтове за UI елементи (бутони, етикети, списъци) и персонализирани само за акцентна типография (заглавия, банери). Кеширайте Typeface на Android чрез Map, а UIFont на iOS — чрез статични променливи.
object FontCache {
private val cache = mutableMapOf<String, Typeface>()
fun get(context: Context, fontId: Int): Typeface {
return cache.getOrPut(fontId.toString()) {
ResourcesCompat.getFont(context, fontId)
}
}
}
// Употреба в RecyclerView
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.textView.typeface = FontCache.get(context, R.font.montserrat_regular)
}
Зареждането на Typeface в onBindViewHolder е допустимо само при наличие на кеш. Без кеш всяко извикване на createFromAsset създава нов обект и чете файла от диска. При скролване на RecyclerView това причинява забележими забавяния. Кешът решава проблема, тъй като шрифтът се зарежда веднъж и се използва повторно.
Често задавани въпроси
OTF — оптималният избор за мобилни приложения. Поддържа OpenType функции (лигатури, алтернативни глифове) при същия размер като TTF. За спестяване на място използвайте вариативни шрифтове TTX или OTF с subsetting. WOFF2 е подходящ само за Android 10+ и не се поддържа на iOS в нативни приложения.
Да. Google Fonts предоставя шрифтове под лиценз OFL (Open Font License) за търговска употреба. Шрифтовете могат да бъдат изтеглени от fonts.google.com и добавени в проекта. Android поддържа Downloadable Fonts чрез Google Play Services, което позволява да не се включват файлове с шрифтове в APK, а да се зареждат при първа употреба.
Най-честите причини: файлът не е добавен в target (iOS), не е посочен в Info.plist (iOS), файлът не е в res/font (Android), посочено е неправилно PostScript име, файлът е повреден. За диагностика на iOS покажете UIFont.familyNames в конзолата. На Android използвайте FontLoader за отстраняване на грешки при зареждане на шрифтове от assets.
Използвайте subsetting (pyftsubset) за премахване на неизползвани знаци — намалява размера с 50-80%. Прилагайте вариативни шрифтове вместо 10 отделни файла. Използвайте WOFF2 компресия за Android 10+. Конфигурирайте ProGuard за объркване на пътищата до шрифтове. За iOS използвайте ресурси при поискване.
Препоръчва се да се ограничите до 2-3 семейства (включително различни стилове). Всяко семейство добавя 200 KB — 3 MB към размера на приложението. Системните шрифтове не натоварват приложението, затова за UI елементи използвайте системни шрифтове, а персонализираните оставете за заглавия и акцентни блокове.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също