Custom Font est un fichier de police (TTF, OTF, WOFF2) qu'un développeur ajoute à une application mobile pour remplacer la police système par défaut. Les polices personnalisées sont utilisées pour créer un style visuel unique, maintenir la cohérence de la marque et améliorer la lisibilité dans différentes langues. Selon Apple Fonts, les polices personnalisées sont prises en charge sur toutes les plateformes Apple, et Android fournit le mécanisme Font Family pour simplifier le chargement. L'intégration correcte d'une police a un impact critique sur la typographie et la perception générale de l'application.
Points clés
Custom Font (police personnalisée) est un fichier typographique qui ne fait pas partie de l'ensemble de polices par défaut du système d'exploitation. Les développeurs ajoutent ces polices à leurs projets pour une typographie unique et cohérente avec la marque. Les polices personnalisées peuvent être des polices commerciales payantes ou des polices open source gratuites, comme Inter, Montserrat ou une version personnalisée de Roboto.
Les cas d'utilisation typiques des polices personnalisées incluent : les logos et titres d'applications de marque, les applications de lecture avec des exigences typographiques spécifiques, les jeux avec des polices thématiques et les applications pour les langues non latines où la police système ne prend pas en charge les glyphes nécessaires. Selon Google Fonts, plus de 60 % des applications du top 100 personnalisent leurs polices pour se différencier visuellement.
Les polices système (San Francisco sur iOS, Roboto sur Android) sont optimisées pour les interfaces mais ne conviennent pas à la typographie de marque. Une police personnalisée renforce la reconnaissance de la marque, peut inclure des caractères spéciaux (polices d'icônes) et améliore la lisibilité pour des publics spécifiques. Cependant, l'utilisation excessive de polices différentes dégrade l'UX — il est recommandé de ne pas utiliser plus de 2 à 3 familles par application.
Les plateformes mobiles prennent en charge plusieurs formats de police. TrueType (TTF) est le format le plus courant, compatible avec toutes les versions d'iOS et d'Android. OpenType (OTF) est une extension de TTF avec prise en charge des ligatures, des glyphes alternatifs et des fonctionnalités OpenType. Les deux formats ont les extensions .ttf et .otf et fonctionnent de manière identique sur les plateformes mobiles.
WOFF2 (Web Open Font Format 2) est un format compressé pour le Web, pris en charge sur Android à partir de la version 10. WOFF2 offre une compression de 30 à 50 % par rapport au TTF. Pour iOS, WOFF2 est pris en charge via Safari, mais les applications natives nécessitent une conversion en TTF/OTF. Les polices variables (Variable Fonts) sont un format moderne qui stocke tous les poids dans un seul fichier.
| Format | iOS | Android | Compression | Caractéristiques |
|---|---|---|---|---|
| TTF | Oui | Oui | Non | Format standard, large compatibilité |
| OTF | Oui | Oui | Non | Fonctionnalités OpenType, ligatures, glyphes alternatifs |
| WOFF2 | Via Safari | API 29+ | 30 à 50 % | Compressé, économise la taille de l'APK |
| Variable | iOS 11+ | API 29+ | Élevée | Un seul fichier pour tous les poids |
Pour le développement mobile, il est recommandé d'utiliser OTF comme format principal — il prend en charge les fonctionnalités OpenType avec la même taille que TTF. Pour économiser de l'espace APK, utilisez la compression via woff2 ou le chargement de polices à la demande.
Le processus d'intégration d'une police personnalisée dans iOS comprend deux étapes : ajouter le fichier au bundle du projet et l'enregistrer dans Info.plist. Le fichier de police est placé dans le répertoire du projet (généralement Resources/Fonts) et inclus dans la cible (target). Dans Info.plist, un tableau UIAppFonts (Fonts provided by application) est ajouté avec les noms des fichiers de police, y compris l'extension.
Après l'enregistrement, la police est accessible via UIFont(name:size:) en utilisant son nom PostScript. Le nom PostScript peut être trouvé via UIFont.familyNames et UIFont.fontNames(forFamilyName:). Si le nom est incorrect, UIFont(name:size:) retourne nil. Pour le débogage, il est recommandé d'afficher toutes les polices enregistrées à l'écran au premier lancement.
Parcourons le cycle complet d'intégration de la police Montserrat dans un projet iOS en Swift. Le fichier Montserrat-Regular.ttf est ajouté au projet, déclaré dans Info.plist, puis chargé via UIFont et appliqué à un UILabel. Chaque poids (regular, bold, italic) nécessite un fichier séparé et une entrée séparée dans Info.plist.
// 1. Dans Info.plist : UIAppFonts → "Montserrat-Regular.ttf"
// 2. Charger la police dans le code
guard let customFont = UIFont(name: "Montserrat-Regular", size: 16) else {
// repli vers la police système
label.font = UIFont.systemFont(ofSize: 16)
return
}
label.font = customFont
// 3. Utiliser dans NSAttributedString
let attributes = [NSAttributedString.Key.font: customFont]
let attributed = NSAttributedString(string: "Text", attributes: attributes)
La gestion du cas où la police n'est pas chargée (UIFont retourne nil) est obligatoire. Au lieu de planter l'application, utilisez la police système comme solution de repli. Ceci est particulièrement important pour les polices chargées depuis le réseau ou ajoutées à des modules optionnels.
Pour les polices téléchargées à la demande, CTFontManagerRegisterGraphicsFont est utilisé. Cette méthode enregistre une police à partir de données en mémoire (Data) et la rend disponible pour UIFont. Après utilisation, la police peut être désenregistrée via CTFontManagerUnregisterGraphicsFont. Le chargement dynamique est utile pour les applications avec un grand ensemble de polices dont toutes ne sont pas nécessaires immédiatement.
Sur Android, les polices personnalisées sont ajoutées via le système de ressources res/font. Les fichiers TTF ou OTF sont placés dans res/font/, après quoi des ressources XML Font Family sont créées pour regrouper les poids. À partir d'Android 8.0 (API 26), c'est la seule méthode recommandée. Pour les versions plus anciennes, les assets et Typeface.createFromAsset sont utilisés.
Un XML Font Family décrit la correspondance entre un poids (regular, bold, italic) et un fichier de police. Dans la mise en page XML, l'attribut android:fontFamily="@font/my_font" sélectionne automatiquement le fichier correct lors de l'appel de setTypeface avec le style correspondant. Cela simplifie la typographie — il suffit de spécifier la famille dans le thème, et Android choisira automatiquement la version grasse lors de l'appel de setTypeface(textView, Typeface.BOLD).
Créez un fichier XML dans res/font/my_font.xml listant tous les fichiers de police pour différents poids. Chaque élément a les attributs fontStyle (normal/italic) et fontWeight (100 à 900). Ensuite, dans la mise en page, spécifiez android:fontFamily="@font/my_font". Lorsque textStyle="bold" est utilisé, Android sélectionne automatiquement le fichier avec 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>
Lors de l'utilisation de Font Family, l'approche par ressources met automatiquement en cache les polices et sélectionne le poids correct. Si le poids requis n'est pas disponible dans la famille, Android le synthétise à partir du poids disponible le plus proche. Pour un contrôle précis de la police, utilisez Typeface.create() avec une référence explicite au fichier.
Dans les frameworks multiplateformes, l'intégration des polices est unifiée. Flutter utilise pubspec.yaml pour déclarer les polices : les fichiers sont placés dans le dossier fonts/ du projet, puis listés dans la section fonts avec la famille et les poids. La police est ensuite appliquée via TextStyle(fontFamily: 'Montserrat') ou dans le thème de l'application. Flutter prend en charge TTF et OTF.
React Native utilise deux approches : native (via Info.plist et res/font) ou via des bibliothèques telles que react-native-vector-icons et @expo-google-fonts. Expo simplifie le processus — les polices sont chargées via expo-font : Font.loadAsync({ 'Montserrat': require('./assets/fonts/Montserrat.ttf') }). React Navigation et les thèmes permettent de définir une police globalement.
Déclaration des polices dans pubspec.yaml et application dans le thème MaterialApp. Les fichiers Montserrat-Regular.ttf et Montserrat-Bold.ttf sont placés dans fonts/. Après la déclaration, la police est accessible via TextStyle dans toute l'application. Flutter utilise automatiquement le fichier gras lorsque fontWeight: FontWeight.bold est spécifié.
// pubspec.yaml
flutter:
fonts:
- family: Montserrat
fonts:
- asset: fonts/Montserrat-Regular.ttf
- asset: fonts/Montserrat-Bold.ttf
weight: 700
// Utilisation dans le thème
MaterialApp(
theme: ThemeData(
textTheme: TextTheme(
headlineLarge: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.bold,
fontSize: 28
)
)
)
)
Si Flutter ne trouve pas une police au chemin spécifié, l'application utilise la police de repli du système sans erreur. Pour le débogage, activez checkConsistency dans MaterialApp — il vérifie la disponibilité des polices et affiche des avertissements dans la console lorsque des polices sont manquantes.
La taille de l'APK et de l'IPA dépend directement du nombre de polices incluses. Un seul fichier TTF pèse 50 à 500 Ko pour le jeu de caractères latins et jusqu'à 2 à 5 Mo pour les polices prenant en charge le cyrillique, les caractères CJK ou d'autres ensembles étendus. Dix polices peuvent ajouter 10 à 20 Mo à la taille de l'application, ce qui est critique pour les téléchargements mobiles.
Pour l'optimisation, utilisez le subsetting — suppression des caractères inutilisés du fichier de police. Des outils comme glyphhanger, fonttools (pyftsubset) et Google Webfont Optimizer créent une version de la police avec uniquement les glyphes nécessaires (latin + cyrillique + chiffres + ponctuation). Cela réduit la taille de 50 à 80 %. Sur iOS, des ressources à la demande peuvent être utilisées pour les polices qui ne sont pas nécessaires au premier lancement.
Une police variable (Variable Font) est un seul fichier contenant tous les poids, de Thin à Black et de Condensed à Expanded. Une police variable peut remplacer 10 à 20 fichiers séparés avec des poids différents. La taille d'un tel fichier est approximativement égale à 1 à 2 fichiers statiques. Prise en charge : iOS 11+, Android 10+, Flutter (via FontVariation), React Native (via des bibliothèques personnalisées).
Utilisez WOFF2 pour réduire la taille des polices de 30 à 50 %. Sur Android avec API 29, WOFF2 peut être utilisé directement. Pour iOS, WOFF2 doit être converti en TTF avant l'enregistrement. Les polices utilisées uniquement lors de l'intégration ou sur des écrans spécifiques doivent être chargées via des ressources à la demande (iOS) ou Dynamic Feature (Android) — elles ne seront pas incluses dans l'APK de base.
Les polices personnalisées affectent les performances de deux manières : le temps de chargement et la mémoire. Lors du premier accès, le système lit le fichier sur le disque, analyse les tables de la police et crée des structures internes pour le rendu. Pour une police de 1 Mo, cela prend 20 à 50 ms. La mise en cache après le premier chargement élimine le délai lors des accès suivants.
Mémoire : chaque police chargée est stockée dans le cache du processus. Les polices système sont préchargées ; les polices personnalisées sont chargées lors de la première utilisation. En mémoire, une police occupe environ 2 à 3 fois plus d'espace que sur le disque en raison des structures analysées : tables cmap, glyf, head, hmtx. Pour 5 polices personnalisées de taille moyenne (3 Mo au total), environ 6 à 9 Mo de RAM sont nécessaires.
Limitez les polices personnalisées à 2 à 3 familles par application. Utilisez des polices variables pour remplacer plusieurs poids. Appliquez les polices système pour les éléments d'interface (boutons, étiquettes, listes) et les polices personnalisées uniquement pour la typographie d'accent (titres, bannières). Mettez en cache Typeface sur Android via une Map et UIFont sur iOS via des variables statiques.
object FontCache {
private val cache = mutableMapOf<String, Typeface>()
fun get(context: Context, fontId: Int): Typeface {
return cache.getOrPut(fontId.toString()) {
ResourcesCompat.getFont(context, fontId)
}
}
}
// Utilisation dans RecyclerView
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.textView.typeface = FontCache.get(context, R.font.montserrat_regular)
}
Le chargement de Typeface dans onBindViewHolder n'est acceptable qu'avec la mise en cache. Sans cache, chaque appel de createFromAsset crée un nouvel objet et lit le fichier sur le disque. Lors du défilement de RecyclerView, cela provoque des ralentissements notables. Le cache résout le problème car la police est chargée une fois et réutilisée.
Questions fréquentes
OTF est le choix optimal pour les applications mobiles. Il prend en charge les fonctionnalités OpenType (ligatures, glyphes alternatifs) avec la même taille que TTF. Pour économiser de l'espace, utilisez des polices variables (TTX ou OTF) avec subsetting. WOFF2 ne convient qu'à Android 10+ et n'est pas pris en charge sur iOS dans les applications natives.
Oui. Google Fonts fournit des polices sous licence OFL (Open Font License) pour un usage commercial. Les polices peuvent être téléchargées depuis fonts.google.com et ajoutées au projet. Android prend en charge les polices téléchargeables via Google Play Services, ce qui permet de ne pas inclure les fichiers de police dans l'APK et de les charger lors de la première utilisation.
Les raisons les plus courantes : le fichier n'est pas ajouté à la cible (iOS), pas déclaré dans Info.plist (iOS), le fichier n'est pas dans res/font (Android), le nom PostScript est incorrect ou le fichier est corrompu. Pour le diagnostic sur iOS, imprimez UIFont.familyNames dans la console. Sur Android, utilisez FontLoader pour déboguer le chargement des polices à partir des assets.
Utilisez le subsetting (pyftsubset) pour supprimer les caractères inutilisés — cela réduit la taille de 50 à 80 %. Utilisez des polices variables au lieu de 10 fichiers séparés. Utilisez la compression WOFF2 pour Android 10+. Configurez ProGuard pour obscurcir les chemins des polices. Pour iOS, utilisez des ressources à la demande.
Il est recommandé de se limiter à 2 à 3 familles (y compris les différents poids). Chaque famille ajoute 200 Ko à 3 Mo à la taille de l'application. Les polices système ne surchargent pas l'application, donc utilisez les polices système pour les éléments d'interface et réservez les polices personnalisées pour les titres et les blocs d'accent.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi