Custom Font w programowaniu mobilnym — co to jest, formaty i zastosowanie

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

Custom Font — to plik czcionki (TTF, OTF, WOFF2), który programista dodaje do aplikacji mobilnej w celu zastąpienia domyślnej czcionki systemowej. Niestandardowe czcionki są używane do tworzenia unikalnego stylu wizualnego, zgodności z brandbookiem i poprawy czytelności w różnych językach. Według danych Apple Fonts, niestandardowe czcionki są obsługiwane na wszystkich platformach Apple, a Android udostępnia mechanizm Font Family w celu uproszczenia ładowania. Prawidłowe podłączenie czcionki ma krytyczny wpływ na typografię i ogólny odbiór aplikacji.

Najważniejsze

  • Custom Font — plik czcionki dodawany do aplikacji w celu zastąpienia systemowego kroju
  • Podstawowe formaty: TTF (TrueType), OTF (OpenType), WOFF2 (Web Open Font Format)
  • iOS podłącza czcionki przez Info.plist i UIFont, Android — przez res/font i Typeface
  • Każda czcionka dodaje 50 KB — 5 MB do rozmiaru APK lub IPA
  • Czcionki zmienne pozwalają przechowywać wszystkie kroje w jednym pliku

Co to jest Custom Font?

Custom Font (niestandardowa czcionka) — to plik z krojem, który nie wchodzi w skład standardowego zestawu czcionek systemu operacyjnego. Programiści dodają takie czcionki do projektu w celu uzyskania unikalnej typografii zgodnej z marką. Niestandardowe czcionki mogą być zarówno płatnymi komercyjnymi krojami, jak i darmowymi czcionkami open-source, na przykład Inter, Montserrat, Roboto (wersja niestandardowa).

Typowe scenariusze użycia niestandardowych czcionek: logotypy i nagłówki aplikacji brandingowych, aplikacje do czytania ze szczególnymi wymaganiami typograficznymi, gry z tematycznymi czcionkami, aplikacje dla języków niełacińskich, gdzie czcionka systemowa nie obsługuje potrzebnych glifów. Według danych Google Fonts, ponad 60% aplikacji w top-100 dostosowuje czcionki w celu wizualnej dyferencjacji.

Po co są potrzebne niestandardowe czcionki

Systemowe czcionki (San Francisco w iOS, Roboto w Android) są zoptymalizowane pod interfejsy, ale nie nadają się do typografii brandingowej. Niestandardowa czcionka wzmacnia rozpoznawalność marki, może zawierać specjalne symbole (czcionki ikon) i poprawia czytelność dla określonych grup odbiorców. Jednak nadmierne użycie różnych czcionek pogarsza UX — zaleca się nie więcej niż 2-3 rodziny na aplikację.

Formaty czcionek dla aplikacji mobilnych

Platformy mobilne obsługują kilka formatów czcionek. TrueType (TTF) — najbardziej rozpowszechniony format, kompatybilny ze wszystkimi wersjami iOS i Android. OpenType (OTF) — rozszerzenie TTF z obsługą ligatur, alternatywnych glifów i funkcji OpenType. Oba formaty mają rozszerzenia .ttf i .otf i działają identycznie na platformach mobilnych.

WOFF2 (Web Open Font Format 2) — skompresowany format dla sieci, obsługiwany w Android od wersji 10. WOFF2 zapewnia kompresję do 30-50% względem TTF. Dla iOS WOFF2 jest obsługiwany przez Safari, ale w aplikacjach natywnych wymagana jest konwersja do TTF/OTF. Variable Fonts (czcionki zmienne) — nowoczesny format przechowujący wszystkie kroje w jednym pliku.

FormatiOSAndroidKompresjaCechy
TTFTakTakNieStandardowy format, szeroka kompatybilność
OTFTakTakNieFunkcje OpenType, ligatury, alternatywne glify
WOFF2Przez SafariAPI 29+30-50%Skompresowany, do oszczędzania rozmiaru APK
VariableiOS 11+API 29+WysokaJeden plik dla wszystkich krojów

Do programowania mobilnego zaleca się używanie OTF jako głównego formatu — obsługuje funkcje OpenType przy tym samym rozmiarze co TTF. Aby zaoszczędzić miejsce w APK, używaj kompresji przez woff2 lub ładowanie czcionek na żądanie.

Podłączanie niestandardowych czcionek w iOS

Proces podłączania niestandardowej czcionki w iOS składa się z dwóch kroków: dodanie pliku do bundle projektu i rejestracja w Info.plist. Plik czcionki umieszczany jest w katalogu projektu (zwykle Resources/Fonts) i włączany do targetu. W Info.plist dodaje się tablicę UIAppFonts (Fonts provided by application) z nazwami plików czcionek, wraz z rozszerzeniem.

Po rejestracji czcionka jest dostępna przez UIFont(name:size:) pod nazwą PostScript. Nazwę PostScript można sprawdzić przez UIFont.familyNames i UIFont.fontNames(forFamilyName:). Jeśli nazwa jest nieprawidłowa, UIFont(name:size:) zwraca nil. Do debugowania zaleca się wyświetlenie wszystkich zarejestrowanych czcionek na ekranie przy pierwszym uruchomieniu.

Przykład podłączenia

Rozpatrzmy pełny cykl podłączania czcionki Montserrat w projekcie iOS w Swift. Plik Montserrat-Regular.ttf jest dodawany do projektu, wskazywany w Info.plist, następnie ładowany przez UIFont i stosowany do UILabel. Dla każdego kroju (regular, bold, italic) dodawany jest osobny plik i osobny wpis w Info.plist.

swift
// 1. W Info.plist: UIAppFonts → "Montserrat-Regular.ttf"
// 2. Załaduj czcionkę w kodzie
guard let customFont = UIFont(name: "Montserrat-Regular", size: 16) else {
    // fallback do czcionki systemowej
    label.font = UIFont.systemFont(ofSize: 16)
    return
}
label.font = customFont
// 3. Użyj w NSAttributedString
let attributes = [NSAttributedString.Key.font: customFont]
let attributed = NSAttributedString(string: "Text", attributes: attributes)

Obsługa sytuacji, gdy czcionka nie została załadowana (UIFont zwraca nil) — obowiązkowa. Zamiast awarii aplikacji użyj systemowej czcionki jako fallback. Jest to szczególnie ważne dla czcionek ładowanych z sieci lub dodawanych do opcjonalnych modułów.

Dynamiczne ładowanie przez CTFontManager

Do czcionek pobieranych na żądanie używany jest CTFontManagerRegisterGraphicsFont. Ta metoda rejestruje czcionkę z danych w pamięci (Data) i udostępnia ją dla UIFont. Po użyciu czcionkę można wyrejestrować przez CTFontManagerUnregisterGraphicsFont. Dynamiczne ładowanie jest przydatne dla aplikacji z dużym zestawem czcionek, gdzie nie wszystkie są potrzebne od razu.

Podłączanie niestandardowych czcionek w Android

W Android niestandardowe czcionki dodawane są przez system zasobów res/font. Pliki TTF lub OTF umieszczane są w res/font/, po czym tworzone są zasoby XML Font Family do grupowania krojów. Począwszy od Android 8.0 (API 26) jest to jedyny zalecany sposób. Dla starszych wersji używane są assets i Typeface.createFromAsset.

XML Font Family opisuje dopasowanie między krojem (regular, bold, italic) a plikiem czcionki. W znacznikach XML atrybut android:fontFamily="@font/my_font" automatycznie wybiera odpowiedni plik przy setTypeface z odpowiednim stylem. Upraszcza to typografię — wystarczy wskazać rodzinę w temacie, a Android sam dobierze bold przy wywołaniu setTypeface(textView, Typeface.BOLD).

Tworzenie Font Family

Utwórz plik XML w res/font/my_font.xml, w którym wymienione są wszystkie pliki czcionki dla różnych krojów. Każdy element ma atrybuty fontStyle (normal/italic) i fontWeight (100-900). Następnie w znacznikach wskaż android:fontFamily="@font/my_font". Przy użyciu textStyle="bold" Android automatycznie wybierze plik z fontWeight 700.

xml
<!-- 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>

Przy użyciu Font Family sposób zasobowy automatycznie buforuje czcionki i wybiera prawidłowy krój. Jeśli potrzebna waga jest nieobecna w rodzinie, Android syntetyzuje ją z najbliższej dostępnej. Dla precyzyjnej kontroli nad czcionką używaj Typeface.create() z jawnym wskazaniem pliku.

Podłączanie we Flutter i React Native

W frameworkach wieloplatformowych podłączanie czcionek jest zunifikowane. Flutter używa pubspec.yaml do wskazywania czcionek: pliki umieszczane są w folderze fonts/ projektu, następnie deklarowane w sekcji fonts z podaniem rodziny i krojów. Potem czcionka jest stosowana przez TextStyle(fontFamily: 'Montserrat') lub w temacie aplikacji. Flutter obsługuje TTF i OTF.

React Native używa dwóch podejść: natywnego (przez Info.plist i res/font) lub przez biblioteki react-native-vector-icons i @expo-google-fonts. Expo upraszcza proces — czcionki są ładowane przez expo-font: Font.loadAsync({ 'Montserrat': require('./assets/fonts/Montserrat.ttf') }). React Navigation i tematy pozwalają ustawić czcionkę globalnie.

Przykład we Flutter

Deklaracja czcionek w pubspec.yaml i zastosowanie w temacie MaterialApp. Pliki Montserrat-Regular.ttf i Montserrat-Bold.ttf umieszczane są w fonts/. Po deklaracji czcionka jest dostępna przez TextStyle w całej aplikacji. Flutter automatycznie używa pliku bold przy fontWeight: FontWeight.bold.

dart
// pubspec.yaml
flutter:
  fonts:
    - family: Montserrat
      fonts:
        - asset: fonts/Montserrat-Regular.ttf
        - asset: fonts/Montserrat-Bold.ttf
          weight: 700
// Zastosowanie w temacie
MaterialApp(
  theme: ThemeData(
    textTheme: TextTheme(
      headlineLarge: TextStyle(
        fontFamily: 'Montserrat',
        fontWeight: FontWeight.bold,
        fontSize: 28
      )
    )
  )
)

Jeśli Flutter nie znajdzie czcionki pod wskazaną ścieżką, aplikacja użyje systemowej czcionki zastępczej bez błędów. Do debugowania włącz checkConsistency w MaterialApp — sprawdza on dostępność czcionek i wyświetla ostrzeżenia w konsoli przy brakach.

Optymalizacja rozmiaru czcionek

Rozmiar APK i IPA bezpośrednio zależy od liczby dołączonych czcionek. Jeden plik TTF waży 50-500 KB dla zestawu znaków łacińskich i do 2-5 MB dla czcionek z obsługą cyrylicy, chińskich znaków lub innych rozszerzonych zestawów. Dziesięć czcionek może dodać 10-20 MB do rozmiaru aplikacji, co jest krytyczne dla pobierania mobilnego.

Do optymalizacji używaj subsetting — usuwanie nieużywanych znaków z pliku czcionki. Narzędzia takie jak glyphhanger, fonttools (pyftsubset) i Google Webfont Optimizer tworzą wersję czcionki tylko z potrzebnymi glifami (łacina + cyrylica + cyfry + znaki interpunkcyjne). Zmniejsza to rozmiar o 50-80%. W iOS można używać zasobów on-demand dla czcionek, które nie są potrzebne przy pierwszym uruchomieniu.

Czcionki zmienne

Variable Font (czcionka zmienna) — to jeden plik zawierający wszystkie kroje: od Thin do Black i od Condensed do Expanded. Jedna czcionka zmienna może zastąpić 10-20 osobnych plików z różnymi wagami. Rozmiar takiego pliku jest w przybliżeniu równy 1-2 statycznym plikom. Obsługa: iOS 11+, Android 10+, Flutter (przez FontVariation), React Native (przez biblioteki niestandardowe).

Kompresja i ładowanie na żądanie

Używaj WOFF2 do zmniejszenia rozmiaru czcionek o 30-50%. W Android z API 29 można używać WOFF2 bezpośrednio. Dla iOS wymagana jest konwersja WOFF2 do TTF przed rejestracją. Czcionki używane tylko w onboardingu lub na określonych ekranach ładuj przez zasoby on-demand (iOS) lub Dynamic Feature (Android) — nie trafią one do podstawowego APK.

Wydajność i best practices

Niestandardowe czcionki wpływają na wydajność na dwa sposoby: czas ładowania i pamięć. Przy pierwszym odwołaniu do czcionki system odczytuje plik z dysku, parsuje tabele czcionki i tworzy wewnętrzne struktury do renderowania. Dla czcionki o rozmiarze 1 MB zajmuje to 20-50 ms. Buforowanie po pierwszym załadowaniu eliminuje opóźnienie przy kolejnych odwołaniach.

Pamięć: każda załadowana czcionka przechowywana jest w buforze procesu. Czcionki systemowe są wstępnie załadowane, niestandardowe — ładowane przy pierwszym użyciu. W pamięci czcionka zajmuje około 2-3 razy więcej niż na dysku, ze względu na rozebrane struktury: tabele cmap, glyf, head, hmtx. Dla 5 niestandardowych czcionek średniego rozmiaru (łączny wolumen 3 MB) potrzeba około 6-9 MB RAM.

Zalecenia

Ogranicz liczbę niestandardowych czcionek do 2-3 rodzin na aplikację. Używaj czcionek zmiennych do zastąpienia kilku krojów. Stosuj czcionki systemowe dla elementów UI (przyciski, etykiety, listy), a niestandardowe tylko do typografii akcentowej (nagłówki, banery). Buforuj Typeface w Android przez Mapę, a UIFont w iOS przez zmienne statyczne.

kotlin
object FontCache {
    private val cache = mutableMapOf<String, Typeface>()
    fun get(context: Context, fontId: Int): Typeface {
        return cache.getOrPut(fontId.toString()) {
            ResourcesCompat.getFont(context, fontId)
        }
    }
}
// Zastosowanie w RecyclerView
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.textView.typeface = FontCache.get(context, R.font.montserrat_regular)
}

Ładowanie Typeface w onBindViewHolder jest dopuszczalne tylko przy obecności bufora. Bez bufora każde wywołanie createFromAsset tworzy nowy obiekt i odczytuje plik z dysku. Przy scrollowaniu RecyclerView powoduje to zauważalne opóźnienia. Bufor rozwiązuje problem, ponieważ czcionka ładowana jest raz i ponownie używana.

Często zadawane pytania

Jaki format czcionki jest najlepszy dla aplikacji mobilnych?

OTF — optymalny wybór dla aplikacji mobilnych. Obsługuje funkcje OpenType (ligatury, alternatywne glify) przy tym samym rozmiarze co TTF. Aby zaoszczędzić miejsce, używaj czcionek zmiennych TTX lub OTF z subsetting. WOFF2 nadaje się tylko dla Android 10+ i nie jest obsługiwany w iOS w aplikacjach natywnych.

Czy można używać Google Fonts w aplikacjach mobilnych?

Tak. Google Fonts udostępnia czcionki na licencji OFL (Open Font License) do użytku komercyjnego. Czcionki można pobrać z fonts.google.com i dodać do projektu. Android obsługuje Downloadable Fonts przez Google Play Services, co pozwala nie dołączać plików czcionek do APK, a ładować je przy pierwszym użyciu.

Dlaczego niestandardowa czcionka się nie wyświetla?

Najczęstsze przyczyny: plik nie został dodany do targetu (iOS), nie wskazany w Info.plist (iOS), plik nie w res/font (Android), podano nieprawidłową nazwę PostScript, plik jest uszkodzony. Do diagnostyki w iOS wyświetl UIFont.familyNames w konsoli. W Android używaj FontLoader do debugowania ładowania czcionek z assets.

Jak zmniejszyć rozmiar czcionki w APK?

Używaj subsetting (pyftsubset) do usuwania nieużywanych znaków — zmniejsza rozmiar o 50-80%. Stosuj czcionki zmienne zamiast 10 osobnych plików. Używaj kompresji WOFF2 dla Android 10+. Skonfiguruj ProGuard do zaciemniania ścieżek do czcionek. Dla iOS używaj zasobów on-demand.

Ile niestandardowych czcionek można używać w aplikacji?

Zaleca się ograniczyć do 2-3 rodzin (wliczając różne kroje). Każda rodzina dodaje 200 KB — 3 MB do rozmiaru aplikacji. Czcionki systemowe nie obciążają aplikacji, dlatego do elementów UI używaj systemowych, a niestandardowe zostaw do nagłówków i bloków akcentowych.

Podsumowanie

  • Custom Font — plik czcionki (TTF, OTF, WOFF2) dodawany do aplikacji dla typografii brandingowej
  • iOS: plik w bundle + UIAppFonts w Info.plist + UIFont(name:size:)
  • Android: plik w res/font + XML Font Family + Typeface lub android:fontFamily
  • Flutter: deklaracja w pubspec.yaml + TextStyle(fontFamily:)
  • Optymalizacja: subsetting zmniejsza rozmiar czcionki o 50-80% przy zachowaniu potrzebnych znaków
  • Czcionki zmienne zastępują 10-20 statycznych plików jednym plikiem ze wszystkimi krojami
  • Buforuj czcionki przy ładowaniu — jedna instancja na sesję aplikacji

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ż