Typeface — је класа Android SDK из пакета android.graphics која представља изглед фонта и користи се за прилагођавање текста у TextView и другим UI компонентама. Typeface одређује породицу фонта, његову тежину (normal, bold) и стил (normal, italic). Према Google Developers, Typeface подржава учитавање из TTF, OTF датотека, XML фонтова и системских ресурса. Ово је централна класа за управљање типографијом у Android апликацијама.
Главно
Typeface — је Android класа која инкапсулира информације о фонту: његову породицу (Roboto, Arial, Serif) и модификаторе стила (дебљина, курзив). За разлику од 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 за приказивање целокупног текста, укључујући системски UI, наслове, ознаке и обавештења. Свака апликација може премостити подразумевани фонт кроз тему (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.
Ресурсни начин такође подржава породице фонтова (font family) кроз 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")
}
}
}
// Употреба
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 или family и примењује се на опсег карактера. Ово је једини начин мешања фонтова унутар једног 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" ће се приказати моноширинским фонтом плаве боје, а реч „Kod:" ће остати системским фонтом. 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. Ово је типичан сценарио за апликације са прилагођеном типографијом која се учитава на захтев.
// Сачувај датотеку фонта у интерну меморију
val fontFile = File(context.cacheDir, "downloaded-font.otf")
fontFile.outputStream().use { output ->
// улазни ток из мреже
inputStream.copyTo(output)
}
// Креирај Typeface из датотеке
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.
За учитавање фонта из resources, 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 MB ово траје 10-50 ms на хладном покретању. Кеширање 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. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође