Typeface — co to jest, typy czcionek i praca w Android

Autor: IT Sectr Opublikowano: 2026-07-23 Czas czytania: 9 min

Typeface — to klasa Android SDK z pakietu android.graphics, która reprezentuje krój czcionki i jest używana do personalizacji tekstu w TextView i innych komponentach UI. Typeface określa rodzinę czcionki, jej wagę (normal, bold) i styl (normal, italic). Według Google Developers, Typeface obsługuje ładowanie z plików TTF, OTF, XML-fontów i zasobów systemowych. To centralna klasa do zarządzania typografią w aplikacjach Android.

Najważniejsze

  • Typeface — klasa Android do reprezentacji kroju czcionki z rodziną i stylem
  • Wbudowane style: Typeface.NORMAL, BOLD, ITALIC, BOLD_ITALIC
  • Czcionki są ładowane z zasobów XML, plików TTF/OTF, assets lub folderów systemowych
  • Android 8.0+ obsługuje ładowanie czcionek przez zasoby XML w res/font
  • Typeface.create() tworzy instancję z określoną rodziną i stylem

Czym jest Typeface?

Typeface — to klasa Android, inkapsulująca informację o czcionce: jej rodzinie (Roboto, Arial, Serif) i modyfikatorach stylu (pogrubienie, kursywa). W przeciwieństwie do UIFont w iOS, Typeface nie zawiera informacji o rozmiarze — rozmiar tekstu ustawia się osobno przez właściwość textSize w TextView lub TextStyle w Spannable. Typeface odpowiada tylko za krój i garnitur czcionki.

Klasa dostępna na wszystkich poziomach API. Do Androida 4.4 Typeface obsługiwał tylko ograniczony zestaw czcionek systemowych: DEFAULT, DEFAULT_BOLD, MONOSPACE, SERIF, SANS_SERIF. Począwszy od Androida 8.0 (API 26) pojawiła się obsługa ładowania niestandardowych czcionek przez zasoby XML, a Android 10 dodał obsługę czcionek zmiennych.

Wbudowane stałe Typeface

Android dostarcza kilka wbudowanych instancji Typeface: Typeface.DEFAULT — systemowa czcionka Roboto (Material) lub Noto (AOSP), DEFAULT_BOLD — pogrubiona wersja, MONOSPACE — czcionka o stałej szerokości do kodu, SERIF — czcionka szeryfowa (Noto Serif), SANS_SERIF — bezszeryfowa (Noto Sans). Te stałe są dostępne bez kontekstu i nie wymagają uprawnień do odczytu plików.

Typeface w systemie

System Android używa Typeface do renderowania całego tekstu, włączając systemowe UI, nagłówki, podpisy i powiadomienia. Każda aplikacja może nadpisać domyślną czcionkę przez motyw (android:fontFamily) lub programowo przez setTypeface(). Typeface stosuje się do wszystkich komponentów dziedziczących po TextView: przycisków, EditText i niestandardowych widoków.

Tworzenie Typeface z zasobów

Android 8.0+ pozwala dodawać czcionki do res/font i używać ich przez zasoby XML. Plik czcionki (TTF lub OTF) umieszcza się w res/font, po czym tworzy się referencję R.font.font_name. Typeface ładuje się przez ResourcesCompat.getFont(context, R.font.font_name). Ten sposób jest preferowany, ponieważ czcionka jest kompilowana do APK i obsługuje systemy układania ProGuard.

Sposób zasobowy obsługuje również rodziny czcionek (font family) przez plik XML w res/font: można wskazać kilka plików dla różnych krojów (regular, bold, italic), a system automatycznie wybierze odpowiedni plik przy wywołaniu setTypeface. Upraszcza to typografię — wystarczy ustawić fontFamily w motywie, a Android sam dobierze odpowiedni plik.

Tworzenie Typeface.create

Metoda Typeface.create(Typeface family, int style) tworzy instancję czcionki z określoną rodziną i stylem. Jeśli rodzina ma już żądany styl, zwracana jest istniejąca instancja. Jeśli styl nie istnieje, Android syntetyzuje go — stosuje fałszywe pogrubienie lub sztuczną kursywę do podstawowej czcionki.

kotlin
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

Syntetyzowane pseudo-pogrubienie może wyglądać niskiej jakości na cienkich czcionkach. Dla lepszego rezultatu użyj pliku czcionki z prawdziwym boldem. Typeface.create() z nieistniejącym stylem nie rzuca wyjątku, a zwraca najbliższy dostępny wariant.

Typeface z pliku i assets

Do ładowania Typeface z assets używa się Typeface.createFromAsset(assetManager, path). Czcionkę umieszcza się w katalogu src/main/assets/fonts/, a ścieżkę podaje się względem assets. Ten sposób działa na wszystkich wersjach Androida, ale nie obsługuje rodzin czcionek i wymaga wskazania konkretnego pliku dla każdego kroju.

Metoda Typeface.createFromFile(File) ładuje czcionkę z dowolnego pliku w systemie plików. Jest to przydatne dla czcionek pobranych z sieci lub skopiowanych do wewnętrznego magazynu aplikacji. createFromFile również nie wymaga kontekstu, co jest wygodne dla zadań w tle, ale plik musi być dostępny do odczytu.

Ładowanie z assets z buforowaniem

Wielokrotne ładowanie Typeface z assets przez createFromAsset może prowadzić do tworzenia zduplikowanych obiektów. Każde wywołanie createFromAsset ładuje plik od nowa. Zaleca się zaimplementowanie cache Typeface przez HashMap, gdzie kluczem jest ścieżka do pliku, a wartością — załadowana instancja. Jest to szczególnie istotne dla list z różnymi typami czcionek.

kotlin
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")
        }
    }
}
// Użycie
val typeface = TypefaceCache.getTypeface(context, "Roboto-Bold.ttf")

Cache w pamięci gwarantuje, że jedna czcionka jest ładowana tylko raz na sesję aplikacji. Przy zmianie konfiguracji (obrót ekranu) cache jest zachowany, ponieważ znajduje się w obiekcie companion. Do czyszczenia cache przy braku pamięci użyj WeakHashMap lub nasłuchuj onTrimMemory.

Stosowanie Typeface do TextView

Typeface stosuje się do TextView przez metodę setTypeface(Typeface tf) lub setTypeface(Typeface tf, int style). Drugi wariant pozwala zmienić styl (bold/italic) względem bieżącej czcionki. W XML używa się atrybutu android:fontFamily z referencją do czcionki lub systemowej rodziny. Do programowego ustawienia wywołanie setTypeface(monospaceTypeface) zastąpi czcionkę na wskazaną.

Typeface wpływa na cały tekst TextView. Jeśli wymagana jest inna czcionka w jednej linii, używa się SpannableString z TypefaceSpan. TypefaceSpan przyjmuje Typeface lub family i stosuje się do zakresu znaków. To jedyny sposób mieszania czcionek wewnątrz jednego TextView bez zagnieżdżonych komponentów.

TypefaceSpan dla części tekstu

Zastosuj TypefaceSpan tylko do części ciągu. Na przykład wartość zmiennej w tekście powinna być czcionką o stałej szerokości, a reszta tekstu — systemową. Tworzy się SpannableString, a na żądany zakres ustawia się TypefaceSpan z MONOSPACE Typeface. Pozostała część tekstu pozostaje z oryginalną czcionką TextView.

kotlin
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

Tekst „variableName” wyświetli się czcionką o stałej szerokości w kolorze niebieskim, a słowo „Kod“ pozostanie czcionką systemową. TypefaceSpan można łączyć z dowolnymi innymi spanami dla precyzyjnej kontroli nad każdym fragmentem tekstu.

Niestandardowe czcionki przez Typeface

Android obsługuje kilka formatów czcionek: TrueType (TTF), OpenType (OTF) i Web Open Font Format (WOFF2) od Androida 10. TTF i OTF to główne formaty dla niestandardowych czcionek. XML-fonty (Font Family) nie są osobnym formatem, a służą jako opis, który plik użyć dla każdego kroju.

Do użycia niestandardowej czcionki przez res/font utwórz plik XML rodziny, gdzie wskazujesz ścieżki do plików czcionek dla regular, bold i italic. Następnie w motywie aplikacji ustaw android:fontFamily="@font/custom_family". Wszystkie TextView używające tego motywu automatycznie otrzymają poprawny krój dla każdego stylu.

Ładowanie pobranych czcionek

Jeśli czcionka jest pobierana z sieci, zapisz ją w filesDir lub cacheDir i załaduj przez Typeface.createFromFile. Po załadowaniu zaktualizuj Typeface w TextView. Do asynchronicznego ładowania użyj coroutine lub DownloadManager, a po zakończeniu — wyślij do UI wątku przez Handler. To typowy scenariusz dla aplikacji z niestandardową typografią ładowaną na żądanie.

kotlin
// Zapisz plik czcionki w wewnętrznym magazynie
val fontFile = File(context.cacheDir, "downloaded-font.otf")
fontFile.outputStream().use { output ->
    // strumień wejściowy z sieci
    inputStream.copyTo(output)
}
// Utwórz Typeface z pliku
val downloadedTypeface = Typeface.createFromFile(fontFile)
textView.typeface = downloadedTypeface

Przed załadowaniem sprawdź dostępność pliku: jeśli plik jest uszkodzony lub nieprawidłowy, Typeface.createFromFile rzuci RuntimeException. Zaleca się owinięcie wywołania w try-catch i w razie błędu pozostawienie systemowej czcionki domyślnej.

Typeface w Jetpack Compose

W Jetpack Compose Typeface Android SDK nie jest używany bezpośrednio. Zamiast tego Compose udostępnia FontFamily i FontWeight dla typografii. FontFamily ładuje się przez Font.Resource i Font.File. System typografii Compose ustawia się przez MaterialTheme.typography, gdzie każdemu stylowi (h1, body1, button) można przypisać niestandardową FontFamily.

Do ładowania czcionki z resources Compose używa Font(R.font.font_name, weight, style). Czcionka z assets ładuje się przez Font(assetPath = "fonts/custom.otf", weight, style). Po zdefiniowaniu czcionki jest ona przekazywana do Typography, a następnie stosowana przez MaterialTheme.typography.bodyLarge i podobne style.

Konwersja Typeface na czcionkę Compose

Jeśli istnieje gotowy Typeface utworzony przez Android SDK, można go użyć w Compose przez TypefaceAdapter lub tworząc FontFamily na bazie Typeface. W tym celu pobierz Typeface z Typeface.create i przekaż go do FontFamily.Custom(listOf(Font(typeface))). Zaleca się jednak używanie natywnego podejścia z Font.Resource, ponieważ jest lepiej zoptymalizowane dla Compose.

Wydajność i buforowanie

Ładowanie czcionek z plików to potencjalnie kosztowna operacja. Każde wywołanie Typeface.createFromAsset lub Typeface.createFromFile czyta plik z dysku, parsuje go i tworzy obiekt Typeface. Dla czcionek o rozmiarze 1-2 MB zajmuje to do 10-50 ms przy zimnym starcie. Buforowanie Typeface to obowiązkowa praktyka dla aplikacji z niestandardowymi czcionkami.

Android SDK nie buforuje czcionek utworzonych przez createFromAsset lub createFromFile. W przeciwieństwie do czcionek systemowych, które są wstępnie załadowane w procesie Zygote, niestandardowe czcionki są ładowane przy każdym odwołaniu. Zaleca się używanie LruCache lub ConcurrentHashMap z kluczem z identyfikatora czcionki. Rozmiar cache — 10-20 instancji, co pokrywa typowy zestaw czcionek aplikacji.

Optymalizacja przez Font Family (API 26+)

Android 8.0+ optymalizuje ładowanie czcionek przez XML Font Family. Przy ustawieniu android:fontFamily="@font/my_family" w układzie XML, Android ładuje czcionkę leniwie — tylko gdy komponent staje się widoczny. System buforuje również czcionki załadowane przez ResourcesCompat.getFont() w globalnym cache procesów. To czyni sposób zasobowy najbardziej wydajnym.

Typeface w RecyclerView

Przy użyciu Typeface w adapterach RecyclerView ważne jest, aby nie ładować czcionki w metodzie onBindViewHolder. Wywołaj ładowanie raz przy tworzeniu adaptera lub użyj ViewHolder z wstępnie załadowanym Typeface. Jeśli każdy element listy wymaga unikalnej czcionki, zaimplementuj cache przez WeakHashMap i czyść go przy przewijaniu poza widoczne pozycje, aby oszczędzić pamięć.

Często zadawane pytania

Czym różni się Typeface od FontFamily w Android?

Typeface — to konkretna instancja czcionki do programowego użytku. FontFamily — zasób XML opisujący grupę plików czcionek dla różnych krojów (regular, bold, italic). W runtime FontFamily jest konwertowany na Typeface przez ResourcesCompat.getFont. Typeface można utworzyć bezpośrednio z pliku, pomijając FontFamily.

Jak załadować Typeface bez kontekstu?

Użyj Typeface.createFromFile(File) lub Typeface.DEFAULT. Te metody nie wymagają kontekstu, ponieważ działają z systemem plików lub wbudowanymi stałymi. Do ładowania z assets lub zasobów kontekst jest wymagany, ponieważ potrzebny jest dostęp do AssetManager i zasobów aplikacji.

Czy można używać Typeface w WebView?

Nie, WebView używa właściwości CSS font-family do określania czcionek. Aby użyć niestandardowej czcionki w WebView, umieść plik czcionki w assets i wskaż go przez @font-face w CSS. Typeface Android SDK działa tylko z natywnymi komponentami UI (TextView i pochodnymi).

Czy Typeface obsługuje czcionki zmienne?

Tak, od Androida 10 (API 29). Czcionki zmienne ładuje się przez ResourcesCompat.getFont lub Typeface.createFromFile. Do konfiguracji osi zmienności (weight, width) używa się FontStyle w Compose lub atrybutów XML. Programowo zmienić oś można tylko przez niskopoziomowe API Skia.

Dlaczego setTypeface nie działa dla niektórych czcionek?

Najczęstsze przyczyny: plik czcionki nie istnieje w projekcie, podano nieprawidłową nazwę pliku, czcionka jest uszkodzona lub używany jest syntetyzowany styl, którego nie ma w pliku. Sprawdź, czy plik został dodany do res/font lub assets i czy jego nazwa jest podana bez rozszerzenia w przypadku sposobu zasobowego.

Podsumowanie

  • Typeface — klasa Android do reprezentacji czcionki z rodziną i stylem kroju
  • Wbudowane stałe: DEFAULT, DEFAULT_BOLD, MONOSPACE, SERIF, SANS_SERIF
  • Ładowanie przez ResourcesCompat.getFont, Typeface.createFromAsset, createFromFile
  • XML Font Family (API 26+) — preferowany sposób dla niestandardowych czcionek
  • TypefaceSpan pozwala zastosować czcionkę do części tekstu przez SpannableString
  • Buforowanie Typeface jest obowiązkowe — używaj HashMap lub LruCache
  • W Compose używaj FontFamily i FontWeight zamiast Typeface Android SDK

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również