Comment définir la famille de polices par défaut pour toute l'application Android

283

J'utilise la police légère Roboto dans mon application. Pour définir la police, je dois l'ajouter android:fontFamily="sans-serif-light"à chaque vue. Existe-t-il un moyen de déclarer la police Roboto comme famille de polices par défaut pour toute l'application? J'ai essayé comme ça mais ça ne semblait pas marcher.

<style name="AppBaseTheme" parent="android:Theme.Light"></style>

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:fontFamily">sans-serif-light</item>
</style>
tomrozb
la source
2
Cela pourrait vous aider: stackoverflow.com/a/16883281/1329733
Jacob R
2
Vous pouvez maintenant spécifier des polices personnalisées directement à partir du XML dans android studio 3.0 developer.android.com/guide/topics/ui/look-and-feel/…
Sept

Réponses:

289

La réponse est oui.

Global Roboto light pour TextViewet Buttonclasses:

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:textViewStyle">@style/RobotoTextViewStyle</item>
    <item name="android:buttonStyle">@style/RobotoButtonStyle</item>
</style>

<style name="RobotoTextViewStyle" parent="android:Widget.TextView">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

<style name="RobotoButtonStyle" parent="android:Widget.Holo.Button">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

Sélectionnez simplement le style souhaité dans la liste themes.xml , puis créez votre style personnalisé en fonction de celui d'origine. À la fin, appliquez le style comme thème de l'application.

<application
    android:theme="@style/AppTheme" >
</application>

Cela ne fonctionnera qu'avec des polices intégrées comme Roboto, mais c'était la question. Pour les polices personnalisées (chargées à partir d'actifs par exemple), cette méthode ne fonctionnera pas.

EDIT 13/08/15

Si vous utilisez des thèmes AppCompat, n'oubliez pas de supprimer le android:préfixe. Par exemple:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:textViewStyle">@style/RobotoTextViewStyle</item>
    <item name="buttonStyle">@style/RobotoButtonStyle</item>
</style>

Notez que le buttonStylene contient pas de android:préfixe, mais textViewStyledoit le contenir.

tomrozb
la source
4
D'où avez-vous sans-serif-lighttiré la valeur? Existe-t-il une liste de valeurs valides fontFamilyquelque part? J'ai parcouru les documents, ainsi que les fichiers de thème et de style dans la source Android et je ne trouve rien.
Christopher Perry
34
cela n'est possible que pour l'API de niveau 16 .. le nom "android: fontFamily" n'existe que dans le niveau 16 ou supérieur .. existe-t-il un moyen de le faire également pour l'API 14 par exemple?
Lorenzo Barbagli
3
@LorenzoBarbagli, vous pouvez consulter Calligraphie
Brais Gabin
10
Eh bien, que dois-je faire si j'ai une police personnalisée?
Rohit Tigga
2
oui, je souhaite également ajouter une police personnalisée à l'ensemble de l'application. Comment puis je faire ça ?. Dois-je remplacer TextView et remplacer tous les TextView comme suggéré dans la première réponse
John
145

Avec la sortie d'Android Oreo, vous pouvez utiliser la bibliothèque de support pour atteindre cet objectif.

  1. Vérifiez dans votre application build.gradle si vous avez la bibliothèque de support > = 26.0.0
  2. Ajoutez le dossier " font " à votre dossier de ressources et ajoutez-y vos polices
  3. Référencez votre famille de polices par défaut dans le style principal de votre application:

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
       <item name="android:fontFamily">@font/your_font</item>
       <item name="fontFamily">@font/your_font</item> <!-- target android sdk versions < 26 and > 14 if theme other than AppCompat -->
    </style>

Consultez https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html pour des informations plus détaillées.

João Magalhães
la source
9
Lorsque vous ciblez l'API 26+, cela doit être la méthode acceptée. Lorsque vous utilisez la bibliothèque de support , supprimez simplement le android:préfixe
webo80
2
si vous utilisez uniquement la version non préfixée, c'est ok. Le préfixe sera simplement ignoré sur l'API <26
webo80
2
Cela ne définit pas la police partout ... par exemple, si vous avez des styles qui en dérivent Base.TextAppearance.AppCompat, il n'y est pas utilisé.
Ixx
3
@Ixx, comment remplacer ces styles aussi?
Primož Kralj
2
N'oubliez pas d'utiliser également AppCompatTextView lorsque vous ciblez api <26
Codelicious
38

Pour modifier la police de votre application, procédez comme suit:

  1. Dans le resrépertoire intérieur , créez un nouveau répertoire et appelez-le font.
  2. Insérez votre police .ttf / .otf dans le dossier de polices, assurez-vous que le nom de la police est en lettres minuscules et souligné uniquement.
  3. À l'intérieur res-> values-> à l' styles.xmlintérieur <resources>-> <style>ajoutez votre police <item name="android:fontFamily">@font/font_name</item>.

entrez la description de l'image ici

Maintenant, tout le texte de votre application doit être dans la source que vous ajoutez.

gars
la source
8
tout en utilisant des polices personnalisées, comment puis-je ajouter des polices en gras avec des polices normales?
Rajbir Shienh
Cela ne fonctionne qu'avec l'API de niveau 26 et supérieur, qu'en est-il de l'API 21 et inférieur?
zulkarnain shah
34

LISEZ LES MISES À JOUR CI-DESSOUS

J'ai eu le même problème avec l'incorporation d'une nouvelle police et j'ai finalement réussi à travailler avec l'extension de TextView et à définir la police de caractères à l'intérieur.

public class YourTextView extends TextView {

    public YourTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public YourTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public YourTextView(Context context) {
        super(context);
        init();
    }

    private void init() {
        Typeface tf = Typeface.createFromAsset(context.getAssets(),
            "fonts/helveticaneue.ttf");
        setTypeface(tf);
    }
}

Vous devez modifier les éléments TextView ultérieurement de à en dans chaque élément. Et si vous utilisez UI-Creator dans Eclipse, il n'a parfois pas le droit de TextViews. C'était la seule chose qui fonctionnait pour moi ...

METTRE À JOUR

Aujourd'hui, j'utilise la réflexion pour changer les polices de caractères dans toute l'application sans étendre TextViews. Découvrez ce post SO

MISE À JOUR 2

À partir de l'API niveau 26 et disponible dans la «bibliothèque de support», vous pouvez utiliser

android:fontFamily="@font/embeddedfont"

Pour plus d'informations: Polices en XML

longi
la source
25
Ce n'est pas la solution. J'utilise de nombreuses vues différentes, pas seulement TextView. Je veux définir la police une fois et l'oublier. De plus, votre code crée un nouvel objet pour chaque TextView. Déclarez au moins le champ comme statique pour charger une fois la police des actifs.
tomrozb
2
... eh bien, il y a une fonction de recherche et de remplacement, qui fonctionne très bien dans ce cas
longi
1
Ça ne va pas marcher. Vous ne pouvez pas appeler getContext()lorsque la variable est statique. Vous devez l'implémenter de manière singleton, sinon le code actuel ne sera même pas compilé.
tomrozb
1
j'ai annulé le dernier commit.
longi
1
@tomrozb: D je viens de me rendre compte que les derniers changements rapides que j'ai faits sont dus à vos commentaires! comme vous avez suffisamment de points, vous êtes invités à optimiser vous-même l'exemple de code. sinon on parlera encore du sujet dans quelques années, quand personne ne se souciera plus des smartphones;)
longi
9

Ajoutez cette ligne de code dans votre res / value / styles.xml

<item name="android:fontFamily">@font/circular_medium</item>

le style entier ressemblera à ça

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:fontFamily">@font/circular_medium</item>
</style>

changez "circular_medium" en votre propre nom de police.

nirazverma
la source
6

Ne parlez pas de performances, pour la police personnalisée, vous pouvez avoir une boucle de méthode récursive à travers toutes les vues et définir la police de caractères s'il s'agit d'un TextView:

public class Font {
    public static void setAllTextView(ViewGroup parent) {
        for (int i = parent.getChildCount() - 1; i >= 0; i--) {
            final View child = parent.getChildAt(i);
            if (child instanceof ViewGroup) {
                setAllTextView((ViewGroup) child);
            } else if (child instanceof TextView) {
                ((TextView) child).setTypeface(getFont());
            }
        }
    }

    public static Typeface getFont() {
        return Typeface.createFromAsset(YourApplicationContext.getInstance().getAssets(), "fonts/whateverfont.ttf");
    }
}

Dans toute votre activité, passez-lui le ViewGroup actuel après setContentView et c'est fait:

ViewGroup group = (ViewGroup) getWindow().getDecorView().findViewById(android.R.id.content);
Font.setAllTextView(group);

Pour fragment, vous pouvez faire quelque chose de similaire.

Allen Chan
la source
1
Cela semble génial, mais vous vous demandez comment le faire fonctionner dans le contenu de recyclerView?
Srujan Barai
Je viens d'essayer ça. trop lourd à rendre. Ralentir recyclerViewcomme l'enfer.
Srujan Barai
Totalement déconseillé pour toute vue de liste, cette astuce est juste pour gagner du temps pour coder la vue statique.
Allen Chan
5

Une autre façon de le faire pour l'ensemble de l'application utilise la réflexion basée sur cette réponse

public class TypefaceUtil {
    /**
     * Using reflection to override default typefaces
     * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE
     * OVERRIDDEN
     *
     * @param typefaces map of fonts to replace
     */
    public static void overrideFonts(Map<String, Typeface> typefaces) {
        try {
            final Field field = Typeface.class.getDeclaredField("sSystemFontMap");
            field.setAccessible(true);
            Map<String, Typeface> oldFonts = (Map<String, Typeface>) field.get(null);
            if (oldFonts != null) {
                oldFonts.putAll(typefaces);
            } else {
                oldFonts = typefaces;
            }
            field.set(null, oldFonts);
            field.setAccessible(false);
        } catch (Exception e) {
            Log.e("TypefaceUtil", "Can not set custom fonts");
        }
    }

    public static Typeface getTypeface(int fontType, Context context) {
        // here you can load the Typeface from asset or use default ones
        switch (fontType) {
            case BOLD:
                return Typeface.create(SANS_SERIF, Typeface.BOLD);
            case ITALIC:
                return Typeface.create(SANS_SERIF, Typeface.ITALIC);
            case BOLD_ITALIC:
                return Typeface.create(SANS_SERIF, Typeface.BOLD_ITALIC);
            case LIGHT:
                return Typeface.create(SANS_SERIF_LIGHT, Typeface.NORMAL);
            case CONDENSED:
                return Typeface.create(SANS_SERIF_CONDENSED, Typeface.NORMAL);
            case THIN:
                return Typeface.create(SANS_SERIF_MEDIUM, Typeface.NORMAL);
            case MEDIUM:
                return Typeface.create(SANS_SERIF_THIN, Typeface.NORMAL);
            case REGULAR:
            default:
                return Typeface.create(SANS_SERIF, Typeface.NORMAL);
        }
    }
}

puis chaque fois que vous souhaitez remplacer les polices, vous pouvez simplement appeler la méthode et lui donner une carte des polices de caractères comme suit:

Typeface regular = TypefaceUtil.getTypeface(REGULAR, context);
Typeface light = TypefaceUtil.getTypeface(REGULAR, context);
Typeface condensed = TypefaceUtil.getTypeface(CONDENSED, context);
Typeface thin = TypefaceUtil.getTypeface(THIN, context);
Typeface medium = TypefaceUtil.getTypeface(MEDIUM, context);
Map<String, Typeface> fonts = new HashMap<>();
fonts.put("sans-serif", regular);
fonts.put("sans-serif-light", light);
fonts.put("sans-serif-condensed", condensed);
fonts.put("sans-serif-thin", thin);
fonts.put("sans-serif-medium", medium);
TypefaceUtil.overrideFonts(fonts);

pour un exemple complet, vérifiez

Cela ne fonctionne que pour Android SDK 21 et supérieur pour les versions antérieures, consultez l'exemple complet

Ismail Almetwally
la source
5

Utilisez simplement cette bibliothèque, compilez-la dans votre fichier de notes

complie'me.anwarshahriar:calligrapher:1.0'

et l'utiliser dans la méthode onCreate dans l'activité principale

Calligrapher calligrapher = new Calligrapher(this);
calligrapher.setFont(this, "yourCustomFontHere.ttf", true);

C'est la façon la plus rapide et la plus élégante de le faire.

Mohamed Ayed
la source
2

C'est du travail pour mon projet, source https://gist.github.com/artem-zinnatullin/7749076

Créez le répertoire des polices dans le dossier Asset, puis copiez votre police personnalisée dans le répertoire des polices, par exemple, j'utilise trebuchet.ttf;

Créez une classe TypefaceUtil.java;

import android.content.Context;
import android.graphics.Typeface;
import android.util.Log;

import java.lang.reflect.Field;
public class TypefaceUtil {

    public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) {
        try {
            final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets);

            final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);
            defaultFontTypefaceField.setAccessible(true);
            defaultFontTypefaceField.set(null, customFontTypeface);
        } catch (Exception e) {

        }
    }
}

Modifier le thème dans styles.xml ajouter ci-dessous

<item name="android:typeface">serif</item>

Exemple dans My styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:typeface">serif</item><!-- Add here -->
    </style>


    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:windowFullscreen">true</item>
    </style>
</resources>

Enfin, dans Activity or Fragment onCreate, appelez TypefaceUtil.java

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TypefaceUtil.overrideFont(getContext(), "SERIF", "fonts/trebuchet.ttf");
    }
Irvan Dwi Pangga
la source
0

Android ne fournit pas beaucoup de support pour l'application de polices sur l'ensemble de l'application (voir ce problème ). Vous avez 4 options pour définir la police de l'application entière:

  • Option 1: appliquer la réflexion pour modifier la police système
  • Option 2: créer et sous-classer des classes de vue personnalisées pour chaque vue nécessitant une police personnalisée
  • Option3: implémenter un robot d'exploration qui traverse la hiérarchie des vues pour l'écran actuel
  • Option4: utilisez une bibliothèque tierce.

Les détails de ces options sont disponibles ici .

Phileo99
la source
0

Je sais que cette question est assez ancienne, mais j'ai trouvé une bonne solution. Fondamentalement, vous passez une disposition de conteneur à cette fonction, et elle appliquera la police à toutes les vues prises en charge, et récursivement dans les dispositions enfant:

public static void setFont(ViewGroup layout)
{
    final int childcount = layout.getChildCount();
    for (int i = 0; i < childcount; i++)
    {
        // Get the view
        View v = layout.getChildAt(i);

        // Apply the font to a possible TextView
        try {
            ((TextView) v).setTypeface(MY_CUSTOM_FONT);
            continue;
        }
        catch (Exception e) { }

        // Apply the font to a possible EditText
        try {
            ((TextView) v).setTypeface(MY_CUSTOM_FONT);
            continue;
        }
        catch (Exception e) { }

        // Recursively cicle into a possible child layout
        try {
            ViewGroup vg = (ViewGroup) v;
            Utility.setFont(vg);
            continue;
        }
        catch (Exception e) { }
    }
}
FonzTech
la source
0

à caractère simplement ensemble de l' application à normal, sans, serifou monospace(pas une police personnalisée!), vous pouvez le faire.

définissez un thème et définissez l' android:typefaceattribut sur la police que vous souhaitez utiliser dans styles.xml:

<resources>

    <!-- custom normal activity theme -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <!-- other elements -->
        <item name="android:typeface">monospace</item>
    </style>

</resources>

appliquer le thème à l'ensemble de l'application dans le AndroidManifest.xmlfichier:

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application
        android:theme="@style/AppTheme" >
    </application>
</manifest>

référence android

Eric
la source
Tu es sûr que ça marche? Selon le document Android: "Doit être l'une des valeurs constantes suivantes: normal, sans, serif, monospace".
tomrozb
1
Oh je vois ... vous avez raison ... je n'ai pas compris la question après tout: x Je voulais juste que toute mon application utilise une police monospace (non personnalisée) et je l'ai vu fonctionner alors j'ai posté ceci ici ......... je pense que ma réponse pourrait encore être utile pour ceux qui veulent faire quelque chose de similaire .... alors je vais la modifier et la laisser ici ..... je suis ok est-ce accumule des votes vers le bas. merci d'avoir signalé cela
Eric
Hé @Dave Cruise, ça marche seulement pour le monospace? Je l'ai seulement testé pour monospace ... et rien d'autre .... donc je ne suis pas sûr ... mais selon la documentation, cela devrait fonctionner aussi pour "normal", "sans" et "serif" .. . Je pense que la police est plus générale que la police, donc nous ne pouvons pas l'utiliser pour définir la police de l'application sur une police spécifique comme "consolas" ou quelque chose.
Eric
@Eric oui. je n'en ai aucune idée aussi. monospace fonctionne comme un charme mais pas de chance pour normal, sans ou serif.
Dave Cruise
0

Essayez cette bibliothèque, légère et facile à implémenter

https://github.com/sunnag7/FontStyler

<com.sunnag.fontstyler.FontStylerView
              android:textStyle="bold"
              android:text="@string/about_us"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:paddingTop="8dp"
              app:fontName="Lato-Bold"
              android:textSize="18sp"
              android:id="@+id/textView64" />
Sanny Nagveker
la source
-7

La réponse est non, vous ne pouvez pas. Voir Est-il possible de définir une police personnalisée pour l'ensemble de l'application? pour plus d'informations.

Il existe des solutions de contournement, mais rien dans les lignes de "une seule ligne de code ici et toutes mes polices seront ceci au lieu de cela ".

(Je remercie Google - et Apple - pour cela). Les polices personnalisées ont une place, mais les rendre faciles à remplacer à l'échelle de l'application aurait créé un monde entier d' applications Comic Sans )

Martin Marconcini
la source
41
Pas du tout d'accord avec votre commentaire. Définir une police à l'échelle mondiale devrait être trivial à faire, pas quelque chose qui nécessite les types de solutions de contournement nécessaires. C'est aux développeurs / concepteurs du monde d'éviter les applications "Comic Sans", et non à Google / Apple de les appliquer.
LocalPCGuy
4
Cohérence> Design fantaisie.
Martin Marconcini
14
Cependant, cohérence <fonctionnalité. Nous développons des applications qui affichent l'hébreu biblique. Toutes les polices de base trouvées sur les appareils Android (y compris les dernières polices Android L) effectuent un travail abyssal de rendu des marques de cantillation (et elles font un travail médiocre sur les marques de voyelle, d'ailleurs, bien qu'elles s'améliorent). Nous devons absolument utiliser une police personnalisée dans toute notre application, et nous avons dû écrire beaucoup trop de code simplement pour obtenir toutes les vues requises en l'utilisant.
Ted Hopp du