Typeface — je třída Android SDK z balíčku android.graphics, která reprezentuje řez písma a používá se pro přizpůsobení textu v TextView a dalších UI komponentách. Typeface určuje rodinu písma, jeho váhu (normal, bold) a styl (normal, italic). Podle Google Developers, Typeface podporuje načítání ze souborů TTF, OTF, XML písem a systémových zdrojů. Toto je centrální třída pro správu typografie v Android aplikacích.
Hlavní body
Typeface — je Android třída, která zapouzdřuje informace o písmu: jeho rodinu (Roboto, Arial, Serif) a modifikátory stylu (tučnost, kurzíva). Na rozdíl od UIFont v iOS, Typeface neobsahuje informace o velikosti — velikost textu se nastavuje samostatně přes vlastnost textSize v TextView nebo TextStyle v Spannable. Typeface je zodpovědný pouze za řez a garnituru písma.
Třída je dostupná na všech úrovních API. Do Android 4.4 Typeface podporoval pouze omezenou sadu systémových písem: DEFAULT, DEFAULT_BOLD, MONOSPACE, SERIF, SANS_SERIF. Počínaje Android 8.0 (API 26) se objevila podpora načítání vlastních písem přes XML zdroje a Android 10 přidal podporu variabilních písem.
Android poskytuje několik vestavěných instancí Typeface: Typeface.DEFAULT — systémové písmo Roboto (Material) nebo Noto (AOSP), DEFAULT_BOLD — tučná verze, MONOSPACE — neproporcionální písmo pro kód, SERIF — písmo s patkami (Noto Serif), SANS_SERIF — bezpatkové písmo (Noto Sans). Tyto konstanty jsou dostupné bez kontextu a nevyžadují oprávnění ke čtení souborů.
Systém Android používá Typeface pro vykreslování veškerého textu, včetně systémového UI, nadpisů, popisků a oznámení. Každá aplikace může přepsat výchozí písmo pomocí motivu (android:fontFamily) nebo programově přes setTypeface(). Typeface se aplikuje na všechny komponenty zděděné z TextView: tlačítka, EditText a vlastní zobrazení.
Android 8.0+ umožňuje přidávat písma do res/font a používat je přes XML zdroje. Soubor písma (TTF nebo OTF) se umístí do res/font, poté se vytvoří reference R.font.font_name. Typeface se načítá přes ResourcesCompat.getFont(context, R.font.font_name). Tento způsob je preferován, protože písmo je zkompilováno do APK a podporuje systémy rozvržení ProGuard.
Způsob přes zdroje také podporuje rodiny písem (font family) přes XML soubor v res/font: lze zadat několik souborů pro různé řezy (regular, bold, italic) a systém automaticky vybere správný soubor při volání setTypeface. To zjednodušuje typografii — stačí nastavit fontFamily v motivu a Android sám vybere vhodný soubor.
Metoda Typeface.create(Typeface family, int style) vytváří instanci písma se zadanou rodinou a stylem. Pokud rodina již má požadovaný styl, vrátí se existující instance. Pokud styl neexistuje, Android ho syntetizuje — aplikuje falešné tučné písmo nebo umělou kurzívu na základní písmo.
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
Syntetizované pseudo-tučné písmo může vypadat nekvalitně na tenkých písmech. Pro lepší výsledek použijte soubor písma se skutečným bold řezem. Typeface.create() s neexistujícím stylem nevyhazuje výjimku, ale vrací nejbližší dostupnou variantu.
Pro načtení Typeface z assets se používá Typeface.createFromAsset(assetManager, path). Písmo se umístí do adresáře src/main/assets/fonts/ a cesta se zadává relativně k assets. Tento způsob funguje na všech verzích Android, ale nepodporuje rodiny písem a vyžaduje zadání konkrétního souboru pro každý řez.
Metoda Typeface.createFromFile(File) načítá písmo z libovolného souboru v souborovém systému. To je užitečné pro písma stažená ze sítě nebo zkopírovaná do interního úložiště aplikace. createFromFile také nevyžaduje kontext, což je vhodné pro úlohy na pozadí, ale soubor musí být čitelný.
Opakované načítání Typeface z assets přes createFromAsset může vést k vytváření duplicitních objektů. Každé volání createFromAsset načítá soubor znovu. Doporučuje se implementovat cache Typeface pomocí HashMap, kde klíčem je cesta k souboru a hodnotou je načtená instance. To je důležité zejména pro seznamy s různými typy písem.
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")
}
}
}
// Použití
val typeface = TypefaceCache.getTypeface(context, "Roboto-Bold.ttf")
Cache v paměti zaručuje, že se jedno písmo načítá pouze jednou za relaci aplikace. Při změně konfigurace (otočení obrazovky) cache zůstává, protože je v objektu companion. Pro čištění cache při nedostatku paměti použijte WeakHashMap nebo naslouchejte onTrimMemory.
Typeface se aplikuje na TextView pomocí metody setTypeface(Typeface tf) nebo setTypeface(Typeface tf, int style). Druhá varianta umožňuje změnit styl (bold/italic) vzhledem k aktuálnímu písmu. V XML se používá atribut android:fontFamily s odkazem na písmo nebo systémovou rodinu. Pro programové nastavení volání setTypeface(monospaceTypeface) nahradí písmo zadaným.
Typeface ovlivňuje celý text TextView. Pokud je v jednom řádku potřeba jiné písmo, použije se SpannableString s TypefaceSpan. TypefaceSpan přijímá Typeface nebo family a aplikuje se na rozsah znaků. To je jediný způsob, jak míchat písma v jednom TextView bez vnořených komponent.
Aplikujte TypefaceSpan pouze na část řetězce. Například hodnota proměnné v textu by měla být zobrazena neproporcionálním písmem a zbytek textu systémovým písmem. Vytvoří se SpannableString a na požadovaný rozsah se nastaví TypefaceSpan s MONOSPACE Typeface. Zbytek textu zůstává s původním písmem 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
Text „variableName“ se zobrazí neproporcionálním písmem modré barvy a slovo „Kod:“ zůstane systémovým písmem. TypefaceSpan lze kombinovat s libovolnými dalšími spany pro přesnou kontrolu nad každou částí textu.
Android podporuje několik formátů písem: TrueType (TTF), OpenType (OTF) a Web Open Font Format (WOFF2) od Android 10. TTF a OTF jsou hlavní formáty pro vlastní písma. XML písma (Font Family) nejsou samostatný formát, ale slouží jako popis, který soubor použít pro každý řez.
Pro použití vlastního písma přes res/font vytvořte XML soubor rodiny, kde zadáte cesty k souborům písma pro regular, bold a italic. Poté v motivu aplikace nastavte android:fontFamily="@font/custom_family". Všechny TextView používající tento motiv automaticky získají správný řez pro každý styl.
Pokud se písmo stahuje ze sítě, uložte jej do filesDir nebo cacheDir a načtěte přes Typeface.createFromFile. Po načtení aktualizujte Typeface v TextView. Pro asynchronní načítání použijte coroutine nebo DownloadManager a po dokončení pošlete do UI vlákna přes Handler. To je typický scénář pro aplikace s vlastní typografií načítanou na vyžádání.
// Uložit soubor písma do interního úložiště
val fontFile = File(context.cacheDir, "downloaded-font.otf")
fontFile.outputStream().use { output ->
// vstupní proud ze sítě
inputStream.copyTo(output)
}
// Vytvořit Typeface ze souboru
val downloadedTypeface = Typeface.createFromFile(fontFile)
textView.typeface = downloadedTypeface
Před načtením zkontrolujte dostupnost souboru: pokud je soubor poškozený nebo neplatný, Typeface.createFromFile vyhodí RuntimeException. Doporučuje se obalit volání do try-catch a v případě chyby ponechat výchozí systémové písmo.
V Jetpack Compose se Typeface Android SDK nepoužívá přímo. Místo toho Compose poskytuje FontFamily a FontWeight pro typografii. FontFamily se načítá přes Font.Resource a Font.File. Systém typografie Compose se nastavuje přes MaterialTheme.typography, kde každému stylu (h1, body1, button) lze přiřadit vlastní FontFamily.
Pro načtení písma z resources Compose používá Font(R.font.font_name, weight, style). Písmo z assets se načítá přes Font(assetPath = "fonts/custom.otf", weight, style). Po definování písma se předá do Typography a poté se aplikuje přes MaterialTheme.typography.bodyLarge a podobné styly.
Pokud existuje hotový Typeface vytvořený přes Android SDK, lze jej použít v Compose přes TypefaceAdapter nebo vytvořením FontFamily na základě Typeface. Získejte Typeface z Typeface.create a předejte jej do FontFamily.Custom(listOf(Font(typeface))). Doporučuje se však používat nativní přístup s Font.Resource, protože je lépe optimalizovaný pro Compose.
Načítání písem ze souborů je potenciálně nákladná operace. Každé volání Typeface.createFromAsset nebo Typeface.createFromFile čte soubor z disku, parsuje jej a vytváří objekt Typeface. Pro písma o velikosti 1-2 MB to trvá 10-50 ms při studeném startu. Cache Typeface je povinná praxe pro aplikace s vlastními písmy.
Android SDK neukládá do cache písma vytvořená přes createFromAsset nebo createFromFile. Na rozdíl od systémových písem, která jsou přednačtena v procesu Zygote, vlastní písma se načítají při každém přístupu. Doporučuje se používat LruCache nebo ConcurrentHashMap s klíčem z identifikátoru písma. Velikost cache — 10-20 instancí, což pokrývá typickou sadu písem aplikace.
Android 8.0+ optimalizuje načítání písem přes XML Font Family. Při zadání android:fontFamily="@font/my_family" v XML rozvržení Android načítá písmo líně — pouze když se komponenta stane viditelnou. Systém také ukládá do cache písma načtená přes ResourcesCompat.getFont() v globální cache procesu. To činí způsob přes zdroje nejvýkonnějším.
Při použití Typeface v adaptérech RecyclerView je důležité nenačítat písmo v metodě onBindViewHolder. Zavolejte načtení jednou při vytváření adaptéru nebo použijte ViewHolder s přednačteným Typeface. Pokud každá položka seznamu vyžaduje jedinečné písmo, implementujte cache přes WeakHashMap a čistěte ji při rolování mimo viditelné pozice pro úsporu paměti.
Často kladené otázky
Typeface — je konkrétní instance písma pro programové použití. FontFamily — XML zdroj popisující skupinu souborů písma pro různé řezy (regular, bold, italic). Za běhu se FontFamily převede na Typeface přes ResourcesCompat.getFont. Typeface lze vytvořit přímo ze souboru, bez použití FontFamily.
Použijte Typeface.createFromFile(File) nebo Typeface.DEFAULT. Tyto metody nevyžadují kontext, protože pracují se souborovým systémem nebo vestavěnými konstantami. Pro načítání z assets nebo zdrojů je kontext povinný, protože je potřeba přístup k AssetManager a zdrojům aplikace.
Ne, WebView používá CSS vlastnost font-family pro zadávání písem. Pro použití vlastního písma v WebView umístěte soubor písma do assets a zadejte jej přes @font-face v CSS. Typeface Android SDK funguje pouze s nativními UI komponentami (TextView a jeho potomky).
Ano, od Android 10 (API 29). Variabilní písma se načítají přes ResourcesCompat.getFont nebo Typeface.createFromFile. Pro nastavení os variability (weight, width) se používá FontStyle v Compose nebo XML atributy. Programová změna osy je možná pouze přes nízkoúrovňové API Skia.
Nejčastější příčiny: soubor písma chybí v projektu, je zadán nesprávný název souboru, písmo je poškozené nebo se používá syntetizovaný styl, který v souboru neexistuje. Zkontrolujte, zda byl soubor přidán do res/font nebo assets a zda je jeho název uveden bez přípony v případě způsobu přes zdroje.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také