Custom Font è un file di font (TTF, OTF, WOFF2) che uno sviluppatore aggiunge a un'applicazione mobile per sostituire il font di sistema predefinito. I font personalizzati vengono utilizzati per creare uno stile visivo unico, mantenere la coerenza del marchio e migliorare la leggibilità in diverse lingue. Secondo Apple Fonts, i font personalizzati sono supportati su tutte le piattaforme Apple e Android fornisce il meccanismo Font Family per semplificare il caricamento. L'integrazione corretta del font ha un impatto critico sulla tipografia e sulla percezione generale dell'applicazione.
Punti chiave
Custom Font (font personalizzato) è un file tipografico che non fa parte del set di font predefinito del sistema operativo. Gli sviluppatori aggiungono questi font ai loro progetti per una tipografia unica e coerente con il marchio. I font personalizzati possono essere caratteri tipografici commerciali a pagamento o font open source gratuiti, come Inter, Montserrat o una versione personalizzata di Roboto.
I casi d'uso tipici dei font personalizzati includono: loghi e titoli di app di marca, app di lettura con requisiti tipografici specifici, giochi con font a tema e applicazioni per lingue non latine in cui il font di sistema non supporta i glifi necessari. Secondo Google Fonts, oltre il 60% delle app nella top 100 personalizza i propri font per la differenziazione visiva.
I font di sistema (San Francisco su iOS, Roboto su Android) sono ottimizzati per le interfacce ma non sono adatti per la tipografia del marchio. Un font personalizzato rafforza il riconoscimento del marchio, può includere caratteri speciali (font di icone) e migliora la leggibilità per pubblici specifici. Tuttavia, l'uso eccessivo di font diversi degrada l'esperienza utente — si consiglia di non utilizzare più di 2–3 famiglie per applicazione.
Le piattaforme mobili supportano diversi formati di font. TrueType (TTF) è il formato più comune, compatibile con tutte le versioni di iOS e Android. OpenType (OTF) è un'estensione di TTF con supporto per legature, glifi alternativi e funzionalità OpenType. Entrambi i formati hanno estensioni .ttf e .otf e funzionano in modo identico sulle piattaforme mobili.
WOFF2 (Web Open Font Format 2) è un formato compresso per il web, supportato su Android dalla versione 10. WOFF2 offre una compressione del 30–50% rispetto a TTF. Per iOS, WOFF2 è supportato tramite Safari, ma le applicazioni native richiedono la conversione in TTF/OTF. I font variabili (Variable Fonts) sono un formato moderno che memorizza tutti i pesi in un unico file.
| Formato | iOS | Android | Compressione | Caratteristiche |
|---|---|---|---|---|
| TTF | Sì | Sì | No | Formato standard, ampia compatibilità |
| OTF | Sì | Sì | No | Funzionalità OpenType, legature, glifi alternativi |
| WOFF2 | Tramite Safari | API 29+ | 30–50% | Compresso, risparmia spazio APK |
| Variable | iOS 11+ | API 29+ | Alta | File unico per tutti i pesi |
Per lo sviluppo mobile, si consiglia di utilizzare OTF come formato principale — supporta le funzionalità OpenType con la stessa dimensione di TTF. Per risparmiare spazio APK, utilizzare la compressione tramite woff2 o il caricamento di font su richiesta.
Il processo di integrazione di un font personalizzato in iOS consiste in due passaggi: aggiungere il file al bundle del progetto e registrarlo in Info.plist. Il file del font viene inserito nella directory del progetto (di solito Resources/Fonts) e incluso nel target. In Info.plist, viene aggiunto un array UIAppFonts (Fonts provided by application) con i nomi dei file dei font, inclusa l'estensione.
Dopo la registrazione, il font è accessibile tramite UIFont(name:size:) utilizzando il suo nome PostScript. Il nome PostScript può essere trovato tramite UIFont.familyNames e UIFont.fontNames(forFamilyName:). Se il nome non è corretto, UIFont(name:size:) restituisce nil. Per il debug, si consiglia di visualizzare tutti i font registrati sullo schermo al primo avvio.
Esaminiamo l'intero ciclo di integrazione del font Montserrat in un progetto iOS in Swift. Il file Montserrat-Regular.ttf viene aggiunto al progetto, dichiarato in Info.plist, quindi caricato tramite UIFont e applicato a un UILabel. Ogni peso (regular, bold, italic) richiede un file separato e una voce separata in Info.plist.
// 1. In Info.plist: UIAppFonts → "Montserrat-Regular.ttf"
// 2. Caricare il font nel codice
guard let customFont = UIFont(name: "Montserrat-Regular", size: 16) else {
// ripiegare sul font di sistema
label.font = UIFont.systemFont(ofSize: 16)
return
}
label.font = customFont
// 3. Usare in NSAttributedString
let attributes = [NSAttributedString.Key.font: customFont]
let attributed = NSAttributedString(string: "Text", attributes: attributes)
Gestire il caso in cui il font non viene caricato (UIFont restituisce nil) è obbligatorio. Invece di far crashare l'applicazione, utilizzare il font di sistema come fallback. Questo è particolarmente importante per i font caricati dalla rete o aggiunti a moduli opzionali.
Per i font scaricati su richiesta, viene utilizzato CTFontManagerRegisterGraphicsFont. Questo metodo registra un font da dati in memoria (Data) e lo rende disponibile per UIFont. Dopo l'uso, il font può essere deregistrato tramite CTFontManagerUnregisterGraphicsFont. Il caricamento dinamico è utile per applicazioni con un ampio set di font di cui non tutti sono necessari immediatamente.
Su Android, i font personalizzati vengono aggiunti tramite il sistema di risorse res/font. I file TTF o OTF vengono inseriti in res/font/, dopodiché vengono create risorse XML Font Family per raggruppare i pesi. A partire da Android 8.0 (API 26), questo è l'unico metodo consigliato. Per le versioni precedenti, vengono utilizzati assets e Typeface.createFromAsset.
Un XML Font Family descrive la mappatura tra un peso (regular, bold, italic) e un file di font. Nel layout XML, l'attributo android:fontFamily="@font/my_font" seleziona automaticamente il file corretto quando viene chiamato setTypeface con lo stile corrispondente. Questo semplifica la tipografia — basta specificare la famiglia nel tema e Android sceglierà automaticamente la versione bold quando viene chiamato setTypeface(textView, Typeface.BOLD).
Creare un file XML in res/font/my_font.xml che elenca tutti i file di font per diversi pesi. Ogni elemento ha gli attributi fontStyle (normal/italic) e fontWeight (100–900). Quindi, nel layout, specificare android:fontFamily="@font/my_font". Quando viene utilizzato textStyle="bold", Android seleziona automaticamente il file con fontWeight 700.
<!-- 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>
Quando si utilizza Font Family, l'approccio basato sulle risorse memorizza automaticamente nella cache i font e seleziona il peso corretto. Se il peso richiesto non è disponibile nella famiglia, Android lo sintetizza dal peso disponibile più vicino. Per un controllo preciso sul font, utilizzare Typeface.create() con un riferimento esplicito al file.
Nei framework multipiattaforma, l'integrazione dei font è unificata. Flutter utilizza pubspec.yaml per dichiarare i font: i file vengono inseriti nella cartella fonts/ del progetto e poi elencati nella sezione fonts con la famiglia e i pesi. Il font viene quindi applicato tramite TextStyle(fontFamily: 'Montserrat') o nel tema dell'app. Flutter supporta TTF e OTF.
React Native utilizza due approcci: nativo (tramite Info.plist e res/font) o tramite librerie come react-native-vector-icons e @expo-google-fonts. Expo semplifica il processo — i font vengono caricati tramite expo-font: Font.loadAsync({ 'Montserrat': require('./assets/fonts/Montserrat.ttf') }). React Navigation e i temi consentono di impostare un font a livello globale.
Dichiarazione dei font in pubspec.yaml e applicazione nel tema MaterialApp. I file Montserrat-Regular.ttf e Montserrat-Bold.ttf vengono inseriti in fonts/. Dopo la dichiarazione, il font è accessibile tramite TextStyle in tutta l'applicazione. Flutter utilizza automaticamente il file bold quando viene specificato fontWeight: FontWeight.bold.
// pubspec.yaml
flutter:
fonts:
- family: Montserrat
fonts:
- asset: fonts/Montserrat-Regular.ttf
- asset: fonts/Montserrat-Bold.ttf
weight: 700
// Utilizzo nel tema
MaterialApp(
theme: ThemeData(
textTheme: TextTheme(
headlineLarge: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.bold,
fontSize: 28
)
)
)
)
Se Flutter non trova un font nel percorso specificato, l'applicazione utilizza il font di fallback di sistema senza errori. Per il debug, abilitare checkConsistency in MaterialApp — controlla la disponibilità dei font e stampa avvisi nella console quando i font mancano.
La dimensione di APK e IPA dipende direttamente dal numero di font inclusi. Un singolo file TTF pesa 50–500 KB per il set di caratteri latini e fino a 2–5 MB per font che supportano il cirillico, caratteri CJK o altri set estesi. Dieci font possono aggiungere 10–20 MB alla dimensione dell'applicazione, il che è critico per i download mobili.
Per l'ottimizzazione, utilizzare il subsetting — rimozione dei caratteri non utilizzati dal file di font. Strumenti come glyphhanger, fonttools (pyftsubset) e Google Webfont Optimizer creano una versione del font solo con i glifi necessari (latino + cirillico + cifre + punteggiatura). Questo riduce la dimensione del 50–80%. Su iOS, è possibile utilizzare risorse on-demand per i font che non sono necessari al primo avvio.
Un font variabile (Variable Font) è un singolo file contenente tutti i pesi, da Thin a Black e da Condensed a Expanded. Un font variabile può sostituire 10–20 file separati con pesi diversi. La dimensione di tale file è approssimativamente uguale a 1–2 file statici. Supporto: iOS 11+, Android 10+, Flutter (tramite FontVariation), React Native (tramite librerie personalizzate).
Utilizzare WOFF2 per ridurre la dimensione dei font del 30–50%. Su Android con API 29, WOFF2 può essere utilizzato direttamente. Per iOS, WOFF2 deve essere convertito in TTF prima della registrazione. I font utilizzati solo durante l'onboarding o su schermate specifiche dovrebbero essere caricati tramite risorse on-demand (iOS) o Dynamic Feature (Android) — non verranno inclusi nell'APK di base.
I font personalizzati influiscono sulle prestazioni in due modi: tempo di caricamento e memoria. Al primo accesso, il sistema legge il file dal disco, analizza le tabelle del font e crea strutture interne per il rendering. Per un font di 1 MB, questa operazione richiede 20–50 ms. La memorizzazione nella cache dopo il primo caricamento elimina il ritardo negli accessi successivi.
Memoria: ogni font caricato viene memorizzato nella cache del processo. I font di sistema sono precaricati; i font personalizzati vengono caricati al primo utilizzo. In memoria, un font occupa circa 2–3 volte più spazio che su disco a causa delle strutture analizzate: tabelle cmap, glyf, head, hmtx. Per 5 font personalizzati di dimensioni medie (3 MB totali), sono necessari circa 6–9 MB di RAM.
Limitare i font personalizzati a 2–3 famiglie per applicazione. Utilizzare font variabili per sostituire più pesi. Applicare i font di sistema per gli elementi dell'interfaccia (pulsanti, etichette, elenchi) e font personalizzati solo per la tipografia d'accento (titoli, banner). Memorizzare nella cache Typeface su Android tramite una Map e UIFont su iOS tramite variabili statiche.
object FontCache {
private val cache = mutableMapOf<String, Typeface>()
fun get(context: Context, fontId: Int): Typeface {
return cache.getOrPut(fontId.toString()) {
ResourcesCompat.getFont(context, fontId)
}
}
}
// Utilizzo in RecyclerView
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.textView.typeface = FontCache.get(context, R.font.montserrat_regular)
}
Il caricamento di Typeface in onBindViewHolder è accettabile solo con la cache. Senza cache, ogni chiamata a createFromAsset crea un nuovo oggetto e legge il file dal disco. Durante lo scorrimento di RecyclerView, ciò causa rallentamenti evidenti. La cache risolve il problema perché il font viene caricato una volta e riutilizzato.
Domande frequenti
OTF è la scelta ottimale per le applicazioni mobili. Supporta le funzionalità OpenType (legature, glifi alternativi) con la stessa dimensione di TTF. Per risparmiare spazio, utilizzare font variabili (TTX o OTF) con subsetting. WOFF2 è adatto solo per Android 10+ e non è supportato su iOS nelle applicazioni native.
Sì. Google Fonts fornisce font con licenza OFL (Open Font License) per uso commerciale. I font possono essere scaricati da fonts.google.com e aggiunti al progetto. Android supporta i caratteri scaricabili tramite Google Play Services, consentendo di non includere i file dei font nell'APK e di caricarli al primo utilizzo.
I motivi più comuni: il file non è stato aggiunto al target (iOS), non dichiarato in Info.plist (iOS), il file non si trova in res/font (Android), il nome PostScript non è corretto o il file è danneggiato. Per la diagnosi su iOS, stampare UIFont.familyNames nella console. Su Android, utilizzare FontLoader per eseguire il debug del caricamento dei font da assets.
Utilizzare il subsetting (pyftsubset) per rimuovere i caratteri non utilizzati — riduce la dimensione del 50–80%. Utilizzare font variabili invece di 10 file separati. Utilizzare la compressione WOFF2 per Android 10+. Configurare ProGuard per offuscare i percorsi dei font. Per iOS, utilizzare risorse on-demand.
Si consiglia di limitarsi a 2–3 famiglie (incluse diverse pesature). Ogni famiglia aggiunge da 200 KB a 3 MB alle dimensioni dell'applicazione. I font di sistema non appesantiscono l'app, quindi utilizzare i font di sistema per gli elementi dell'interfaccia e riservare i font personalizzati per titoli e blocchi d'accento.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche