Typeface — este o clasă Android SDK din pachetul android.graphics care reprezintă aspectul fontului și este utilizată pentru personalizarea textului în TextView și alte componente UI. Typeface definește familia fontului, greutatea (normal, bold) și stilul (normal, italic). Potrivit Google Developers, Typeface suportă încărcarea din fișiere TTF, OTF, fonturi XML și resurse de sistem. Aceasta este clasa centrală pentru gestionarea tipografiei în aplicațiile Android.
Principalele
Typeface — este o clasă Android care încapsulează informații despre font: familia sa (Roboto, Arial, Serif) și modificatorii de stil (îngroșare, italic). Spre deosebire de UIFont în iOS, Typeface nu conține informații despre dimensiune — dimensiunea textului se setează separat prin proprietatea textSize în TextView sau TextStyle în Spannable. Typeface răspunde doar pentru aspectul și garnitura fontului.
Clasa este disponibilă la toate nivelurile API. Până la Android 4.4, Typeface suporta doar un set limitat de fonturi de sistem: DEFAULT, DEFAULT_BOLD, MONOSPACE, SERIF, SANS_SERIF. Începând cu Android 8.0 (API 26) a apărut suportul pentru încărcarea fonturilor personalizate prin resurse XML, iar Android 10 a adăugat suport pentru fonturi variabile.
Android oferă mai multe instanțe încorporate Typeface: Typeface.DEFAULT — fontul de sistem Roboto (Material) sau Noto (AOSP), DEFAULT_BOLD — versiunea îngroșată, MONOSPACE — font monospațiat pentru cod, SERIF — font cu serife (Noto Serif), SANS_SERIF — font fără serife (Noto Sans). Aceste constante sunt disponibile fără context și nu necesită permisiuni de citire a fișierelor.
Sistemul Android folosește Typeface pentru redarea întregului text, inclusiv UI de sistem, titluri, etichete și notificări. Fiecare aplicație poate suprascrie fontul implicit prin temă (android:fontFamily) sau programatic prin setTypeface(). Typeface se aplică tuturor componentelor moștenite de la TextView: butoane, EditText și vizualizări personalizate.
Android 8.0+ permite adăugarea fonturilor în res/font și utilizarea lor prin resurse XML. Fișierul font (TTF sau OTF) se plasează în res/font, după care se creează referința R.font.font_name. Typeface se încarcă prin ResourcesCompat.getFont(context, R.font.font_name). Această metodă este preferată deoarece fontul este compilat în APK și suportă sistemele de așezare ProGuard.
Metoda bazată pe resurse suportă și familii de fonturi (font family) printr-un fișier XML în res/font: se pot specifica mai multe fișiere pentru diferite aspecte (regular, bold, italic), iar sistemul va selecta automat fișierul potrivit la apelul setTypeface. Aceasta simplifică tipografia — este suficient să setați fontFamily în temă, iar Android va alege singur fișierul potrivit.
Metoda Typeface.create(Typeface family, int style) creează o instanță de font cu familia și stilul specificat. Dacă familia are deja stilul solicitat, se returnează instanța existentă. Dacă stilul nu există, Android îl sintetizează — aplică o îngroșare falsă sau un italic artificial fontului de bază.
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
Pseudo-îngroșarea sintetizată poate arăta de calitate slabă pe fonturile subțiri. Pentru un rezultat mai bun, utilizați un fișier font cu aspect real bold. Typeface.create() cu un stil inexistent nu aruncă excepție, ci returnează cea mai apropiată variantă disponibilă.
Pentru încărcarea Typeface din assets se folosește Typeface.createFromAsset(assetManager, path). Fontul se plasează în directorul src/main/assets/fonts/, iar calea se specifică relativ la assets. Această metodă funcționează pe toate versiunile Android, dar nu suportă familii de fonturi și necesită specificarea unui fișier concret pentru fiecare aspect.
Metoda Typeface.createFromFile(File) încarcă fontul dintr-un fișier oarecare din sistemul de fișiere. Este utilă pentru fonturile descărcate din rețea sau copiate în stocarea internă a aplicației. createFromFile nu necesită nici context, ceea ce este convenabil pentru sarcini în fundal, dar fișierul trebuie să fie accesibil pentru citire.
Încărcarea repetată a Typeface din assets prin createFromAsset poate duce la crearea de obiecte duplicat. Fiecare apel createFromAsset încarcă fișierul din nou. Se recomandă implementarea unui cache Typeface prin HashMap, unde cheia este calea către fișier, iar valoarea este instanța încărcată. Acest lucru este deosebit de important pentru liste cu diferite tipuri de fonturi.
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")
}
}
}
// Utilizare
val typeface = TypefaceCache.getTypeface(context, "Roboto-Bold.ttf")
Cache-ul în memorie garantează că un font se încarcă doar o singură dată pe sesiunea aplicației. La schimbarea configurației (rotirea ecranului), cache-ul se păstrează deoarece se află în obiectul companion. Pentru curățarea cache-ului la insuficiență de memorie, utilizați WeakHashMap sau ascultați onTrimMemory.
Typeface se aplică la TextView prin metoda setTypeface(Typeface tf) sau setTypeface(Typeface tf, int style). A doua variantă permite modificarea stilului (bold/italic) relativ la fontul curent. În XML se folosește atributul android:fontFamily cu referință la font sau familia de sistem. Pentru setarea programatică, apelul setTypeface(monospaceTypeface) va înlocui fontul cu cel specificat.
Typeface afectează întregul text al TextView. Dacă este necesar un font diferit într-o singură linie, se folosește SpannableString cu TypefaceSpan. TypefaceSpan acceptă Typeface sau family și se aplică la un interval de caractere. Este singurul mod de a amesteca fonturi într-un singur TextView fără componente imbricate.
Aplicați TypefaceSpan doar la o parte din șir. De exemplu, valoarea variabilei în text ar trebui să fie cu font monospațiat, iar restul textului — cu font de sistem. Se creează un SpannableString și pe intervalul dorit se setează TypefaceSpan cu MONOSPACE Typeface. Restul textului rămâne cu fontul original al 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
Textul „variableName" se va afișa cu font monospațiat de culoare albastră, iar cuvântul „Kod:" va rămâne cu fontul de sistem. TypefaceSpan poate fi combinat cu orice alte span-uri pentru un control precis asupra fiecărui fragment de text.
Android suportă mai multe formate de fonturi: TrueType (TTF), OpenType (OTF) și Web Open Font Format (WOFF2) începând cu Android 10. TTF și OTF sunt formatele principale pentru fonturi personalizate. Fonturile XML (Font Family) nu sunt un format separat, ci servesc ca descriere a fișierului de utilizat pentru fiecare aspect.
Pentru utilizarea unui font personalizat prin res/font creați un fișier XML de familie unde specificați căile către fișierele font pentru regular, bold și italic. Apoi, în tema aplicației, setați android:fontFamily="@font/custom_family". Toate TextView-urile care folosesc această temă vor primi automat aspectul corect pentru fiecare stil.
Dacă fontul este descărcat din rețea, salvați-l în filesDir sau cacheDir și încărcați-l prin Typeface.createFromFile. După încărcare, actualizați Typeface în TextView. Pentru încărcare asincronă utilizați coroutine sau DownloadManager, iar după finalizare — postați în firul UI prin Handler. Acesta este un scenariu tipic pentru aplicațiile cu tipografie personalizată încărcată la cerere.
// Salvare fișier font în stocarea internă
val fontFile = File(context.cacheDir, "downloaded-font.otf")
fontFile.outputStream().use { output ->
// flux de intrare din rețea
inputStream.copyTo(output)
}
// Creare Typeface din fișier
val downloadedTypeface = Typeface.createFromFile(fontFile)
textView.typeface = downloadedTypeface
Înainte de încărcare, verificați disponibilitatea fișierului: dacă fișierul este deteriorat sau invalid, Typeface.createFromFile va arunca o RuntimeException. Se recomandă învelirea apelului în try-catch și, în caz de eroare, păstrarea fontului de sistem implicit.
În Jetpack Compose, Typeface Android SDK nu este utilizat direct. În schimb, Compose oferă FontFamily și FontWeight pentru tipografie. FontFamily se încarcă prin Font.Resource și Font.File. Sistemul de tipografie Compose se setează prin MaterialTheme.typography, unde fiecărui stil (h1, body1, button) i se poate atribui o FontFamily personalizată.
Pentru încărcarea fontului din resources, Compose folosește Font(R.font.font_name, weight, style). Fontul din assets se încarcă prin Font(assetPath = "fonts/custom.otf", weight, style). După definirea fontului, acesta este transmis în Typography, apoi aplicat prin MaterialTheme.typography.bodyLarge și stiluri similare.
Dacă există un Typeface gata creat prin Android SDK, acesta poate fi utilizat în Compose prin TypefaceAdapter sau creând o FontFamily pe baza Typeface. Pentru aceasta, obțineți Typeface din Typeface.create și transmiteți-l în FontFamily.Custom(listOf(Font(typeface))). Cu toate acestea, se recomandă utilizarea abordării native cu Font.Resource, deoarece este mai bine optimizată pentru Compose.
Încărcarea fonturilor din fișiere este o operațiune potențial costisitoare. Fiecare apel Typeface.createFromAsset sau Typeface.createFromFile citește fișierul de pe disc, îl parsează și creează un obiect Typeface. Pentru fonturi de 1-2 MB, aceasta durează 10-50 ms la pornirea la rece. Cache-ul Typeface este o practică obligatorie pentru aplicațiile cu fonturi personalizate.
Android SDK nu cachează fonturile create prin createFromAsset sau createFromFile. Spre deosebire de fonturile de sistem care sunt preîncărcate în procesul Zygote, fonturile personalizate se încarcă la fiecare accesare. Se recomandă utilizarea LruCache sau ConcurrentHashMap cu cheia din identificatorul fontului. Dimensiunea cache-ului — 10-20 de instanțe, ceea ce acoperă setul tipic de fonturi al aplicației.
Android 8.0+ optimizează încărcarea fonturilor prin XML Font Family. La specificarea android:fontFamily="@font/my_family" în layout-ul XML, Android încarcă fontul leneș — doar când componenta devine vizibilă. Sistemul cachează și fonturile încărcate prin ResourcesCompat.getFont() în cache-ul global al procesului. Aceasta face metoda bazată pe resurse cea mai performantă.
La utilizarea Typeface în adaptoarele RecyclerView este important să nu încărcați fontul în metoda onBindViewHolder. Apelați încărcarea o singură dată la crearea adaptorului sau utilizați ViewHolder cu Typeface preîncărcat. Dacă fiecare element al listei necesită un font unic, implementați cache-ul prin WeakHashMap și curățați-l la derularea dincolo de pozițiile vizibile pentru a economisi memorie.
Întrebări frecvente
Typeface — este o instanță concretă de font pentru utilizare programatică. FontFamily — o resursă XML care descrie un grup de fișiere de font pentru diferite aspecte (regular, bold, italic). În runtime, FontFamily este convertit în Typeface prin ResourcesCompat.getFont. Typeface poate fi creat direct din fișier, ocolind FontFamily.
Utilizați Typeface.createFromFile(File) sau Typeface.DEFAULT. Aceste metode nu necesită context, deoarece lucrează cu sistemul de fișiere sau constante încorporate. Pentru încărcarea din assets sau resurse, contextul este obligatoriu, deoarece este necesar accesul la AssetManager și resursele aplicației.
Nu, WebView folosește proprietatea CSS font-family pentru specificarea fonturilor. Pentru a utiliza un font personalizat în WebView, plasați fișierul font în assets și specificați-l prin @font-face în CSS. Typeface Android SDK funcționează doar cu componentele native UI (TextView și descendenți).
Da, începând cu Android 10 (API 29). Fonturile variabile se încarcă prin ResourcesCompat.getFont sau Typeface.createFromFile. Pentru configurarea axelor de variabilitate (weight, width) se folosește FontStyle în Compose sau atribute XML. Modificarea programatică a axei este posibilă doar prin API-ul de nivel scăzut Skia.
Cele mai frecvente cauze: fișierul font lipsește din proiect, numele fișierului este incorect, fontul este deteriorat sau se folosește un stil sintetizat care nu există în fișier. Verificați dacă fișierul a fost adăugat în res/font sau assets și dacă numele său este specificat fără extensie în cazul metodei bazate pe resurse.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și