web-dev-qa-db-fra.com

Est-il possible de définir une police personnalisée pour toute l'application?

Je dois utiliser certaines polices pour toute mon application. J'ai le fichier .ttf pour le même . Est-il possible de définir cela comme police par défaut, au démarrage de l'application, puis de l'utiliser ailleurs dans l'application? Quand est-il défini, comment puis-je l'utiliser dans mes XML de mise en page?

253
Samuh

Oui avec réflexion. Cela fonctionne ( sur la base de cette réponse ):

(Remarque: il s’agit d’une solution de contournement due au manque de prise en charge des polices personnalisées. Si vous souhaitez modifier cette situation, n’hésitez pas à voter pour le problème Android ici ). Note: Ne laissez pas les commentaires "moi aussi" sur cette question, tous ceux qui l'ont regardé recevront un email lorsque vous le ferez. Donc, juste "star" il s'il vous plaît.

import Java.lang.reflect.Field;
import Android.content.Context;
import Android.graphics.Typeface;

public final class FontsOverride {

    public static void setDefaultFont(Context context,
            String staticTypefaceFieldName, String fontAssetName) {
        final Typeface regular = Typeface.createFromAsset(context.getAssets(),
                fontAssetName);
        replaceFont(staticTypefaceFieldName, regular);
    }

    protected static void replaceFont(String staticTypefaceFieldName,
            final Typeface newTypeface) {
        try {
            final Field staticField = Typeface.class
                    .getDeclaredField(staticTypefaceFieldName);
            staticField.setAccessible(true);
            staticField.set(null, newTypeface);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

Vous devez ensuite surcharger les quelques polices par défaut, par exemple dans un application class:

public final class Application extends Android.app.Application {
    @Override
    public void onCreate() {
        super.onCreate();
        FontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf");
        FontsOverride.setDefaultFont(this, "MONOSPACE", "MyFontAsset2.ttf");
        FontsOverride.setDefaultFont(this, "SERIF", "MyFontAsset3.ttf");
        FontsOverride.setDefaultFont(this, "SANS_SERIF", "MyFontAsset4.ttf");
    }
}

Bien sûr, si vous utilisez le même fichier de police, vous pouvez l’améliorer pour le charger une seule fois.

Toutefois, j’ai tendance à en remplacer un, par exemple "MONOSPACE", puis à définir un style pour forcer l’application de cette police de caractères à l’échelle large:

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

    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <item name="Android:typeface">monospace</item>
    </style>
</resources>

API 21 Android 5.0

J'ai examiné les rapports dans les commentaires indiquant que cela ne fonctionnait pas et que cela semblait incompatible avec le thème Android:Theme.Material.Light.

Si ce thème n’a pas d’importance pour vous, utilisez un thème plus ancien, par exemple:

<style name="AppTheme" parent="Android:Theme.Holo.Light.DarkActionBar">
    <item name="Android:typeface">monospace</item>
</style>
444
weston

Il existe une grande bibliothèque de polices personnalisées sous Android: Calligraphie

voici un exemple d'utilisation. 

dans Gradle, vous devez insérer cette ligne dans le fichier build.gradle de votre application:

dependencies {
    compile 'uk.co.chrisjenx:calligraphy:2.2.0'
}

puis créez une classe qui étend Application et écrivez ce code:

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
                        .setDefaultFontPath("your font path")
                        .setFontAttrId(R.attr.fontPath)
                        .build()
        );
    }
} 

et dans la classe d'activité, mettez cette méthode avant onCreate:

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
}

et la dernière chose que votre fichier manifeste devrait ressembler à ceci:

<application
   .
   .
   .
   Android:name=".App">

et cela changera toute l'activité à votre police! c'est simple et propre! 

63
Shia G

Bien que cela ne fonctionne pas pour une application entière, cela fonctionnerait pour une activité et pourrait être réutilisé pour toute autre activité. J'ai mis à jour mon code grâce à @ FR073N pour prendre en charge d'autres vues. Je ne suis pas certain des problèmes liés à Buttons, RadioGroups, etc., car ces classes sont toutes étendues à TextView et devraient donc fonctionner correctement. J'ai ajouté une condition booléenne à l'utilisation de la réflexion, car elle semble très compliquée et pourrait compromettre considérablement les performances.

Remarque: comme indiqué, cela ne fonctionnera pas pour le contenu dynamique! Pour cela, il est possible d'appeler cette méthode avec par exemple une méthode onCreateView ou getView, mais cela demande un effort supplémentaire.

/**
 * Recursively sets a {@link Typeface} to all
 * {@link TextView}s in a {@link ViewGroup}.
 */
public static final void setAppFont(ViewGroup mContainer, Typeface mFont, boolean reflect)
{
    if (mContainer == null || mFont == null) return;

    final int mCount = mContainer.getChildCount();

    // Loop through all of the children.
    for (int i = 0; i < mCount; ++i)
    {
        final View mChild = mContainer.getChildAt(i);
        if (mChild instanceof TextView)
        {
            // Set the font if it is a TextView.
            ((TextView) mChild).setTypeface(mFont);
        }
        else if (mChild instanceof ViewGroup)
        {
            // Recursively attempt another ViewGroup.
            setAppFont((ViewGroup) mChild, mFont);
        }
        else if (reflect)
        {
            try {
                Method mSetTypeface = mChild.getClass().getMethod("setTypeface", Typeface.class);
                mSetTypeface.invoke(mChild, mFont); 
            } catch (Exception e) { /* Do something... */ }
        }
    }
}

Ensuite, pour l'utiliser, vous feriez quelque chose comme ceci:

final Typeface mFont = Typeface.createFromAsset(getAssets(),
"fonts/MyFont.ttf"); 
final ViewGroup mContainer = (ViewGroup) findViewById(
Android.R.id.content).getRootView();
HomeActivity.setAppFont(mContainer, mFont);

J'espère que cela pourra aider.

47
Tom

En résumé:

Option n ° 1: Utilisez la réflexion pour appliquer une police de caractères (combinaison de weston & Roger Huang 's answer):

import Java.lang.reflect.Field;
import Android.content.Context;
import Android.graphics.Typeface;

public final class FontsOverride { 

    public static void setDefaultFont(Context context,
            String staticTypefaceFieldName, String fontAssetName) {
        final Typeface regular = Typeface.createFromAsset(context.getAssets(),
                fontAssetName);
        replaceFont(staticTypefaceFieldName, regular);
    } 

    protected static void replaceFont(String staticTypefaceFieldName,final Typeface newTypeface) {
        if (isVersionGreaterOrEqualToLollipop()) {
            Map<String, Typeface> newMap = new HashMap<String, Typeface>();
            newMap.put("sans-serif", newTypeface);
            try {
                final Field staticField = Typeface.class.getDeclaredField("sSystemFontMap");
                staticField.setAccessible(true);
                staticField.set(null, newMap);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        } else {
            try {
                final Field staticField = Typeface.class.getDeclaredField(staticTypefaceFieldName);
                staticField.setAccessible(true);
                staticField.set(null, newTypeface);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } 
        }
    }

} 

Utilisation en classe d'application:

public final class Application extends Android.app.Application {
    @Override 
    public void onCreate() { 
        super.onCreate(); 
        FontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf");
        FontsOverride.setDefaultFont(this, "MONOSPACE", "MyFontAsset2.ttf");
        FontsOverride.setDefaultFont(this, "SERIF", "MyFontAsset3.ttf");
        FontsOverride.setDefaultFont(this, "SANS_SERIF", "MyFontAsset4.ttf");
    } 
} 

configurez un style pour forcer cette application de police de caractères large (basée sur lovefish ):

Pré-sucette:

<resources>
    <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
    </style>

   <!-- Application theme. -->
   <style name="AppTheme" parent="AppBaseTheme">
       <item name="Android:typeface">monospace</item>
   </style>
</resources>

Sucette (API 21):

<resources>
    <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
    </style>

   <!-- Application theme. -->
   <style name="AppTheme" parent="AppBaseTheme">
       <item name="Android:textAppearance">@style/CustomTextAppearance</item>
   </style>

   <style name="CustomTextAppearance">
       <item name="Android:typeface">monospace</item>
   </style>
</resources>

Option2: Sous-classe chaque vue pour laquelle vous devez personnaliser la police, c.-à-d. ListView, EditTextView, Button, etc. (réponse de Palani ):

public class CustomFontView extends TextView {

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

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

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

private void init() { 
    if (!isInEditMode()) {
        Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "Futura.ttf");
        setTypeface(tf);
    } 
} 

Option 3: Implémenter un View Crawler qui traverse la hiérarchie des vues de votre écran actuel:

Variation n ° 1 ( réponse de Tom ):

public static final void setAppFont(ViewGroup mContainer, Typeface mFont, boolean reflect)
{ 
    if (mContainer == null || mFont == null) return;

    final int mCount = mContainer.getChildCount();

    // Loop through all of the children. 
    for (int i = 0; i < mCount; ++i)
    { 
        final View mChild = mContainer.getChildAt(i);
        if (mChild instanceof TextView)
        { 
            // Set the font if it is a TextView. 
            ((TextView) mChild).setTypeface(mFont);
        } 
        else if (mChild instanceof ViewGroup)
        { 
            // Recursively attempt another ViewGroup. 
            setAppFont((ViewGroup) mChild, mFont);
        } 
        else if (reflect)
        { 
            try { 
                Method mSetTypeface = mChild.getClass().getMethod("setTypeface", Typeface.class);
                mSetTypeface.invoke(mChild, mFont); 
            } catch (Exception e) { /* Do something... */ }
        } 
    } 
} 

Utilisation:

final ViewGroup mContainer = (ViewGroup) findViewById(
Android.R.id.content).getRootView();
HomeActivity.setAppFont(mContainer, Typeface.createFromAsset(getAssets(),
"fonts/MyFont.ttf"));

Variation n ° 2: https://coderwall.com/p/qxxmaa/Android-use-a-custom-font-everywhere .

Option n ° 4: Utilisez une tierce partie appelée Calligraphie .

Personnellement, je recommanderais l'option n ° 4, car cela évite beaucoup de maux de tête.

31
Phileo99

Je voudrais améliorer la réponse de weston pour API 21 Android 5.0.

Cause

Sous API 21, la plupart des styles de texte incluent les paramètres fontFamily, tels que:

<style name="TextAppearance.Material">
     <item name="fontFamily">@string/font_family_body_1_material</item>
</style>

Qui applique la police Roboto Regular par défaut:

<string name="font_family_body_1_material">sans-serif</string>

La réponse originale ne permet pas d’appliquer la police monospace, car Android: fontFamily a une priorité plus grande sur l’attribut Android: typeface ( reference ). L’utilisation de Theme.Holo. * Est une solution de contournement valide, car il n’existe pas d’Android: paramètres de fontFamily à l’intérieur.

Solution

Depuis qu'Android 5.0 a placé le caractère système dans la variable statique Typeface.sSystemFontMap ( référence ), nous pouvons utiliser la même technique de réflexion pour le remplacer:

protected static void replaceFont(String staticTypefaceFieldName,
        final Typeface newTypeface) {
    if (isVersionGreaterOrEqualToLollipop()) {
        Map<String, Typeface> newMap = new HashMap<String, Typeface>();
        newMap.put("sans-serif", newTypeface);
        try {
            final Field staticField = Typeface.class
                    .getDeclaredField("sSystemFontMap");
            staticField.setAccessible(true);
            staticField.set(null, newMap);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    } else {
        try {
            final Field staticField = Typeface.class
                    .getDeclaredField(staticTypefaceFieldName);
            staticField.setAccessible(true);
            staticField.set(null, newTypeface);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
28
Roger Huang

son très simple ... 1.Téléchargez et mettez votre police personnalisée dans les actifs..alors écrivez une classe séparée pour la vue de texte comme suit: ici j'ai utilisé la police futura

public class CusFntTextView extends TextView {

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

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

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

private void init() {
    if (!isInEditMode()) {
        Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "Futura.ttf");
        setTypeface(tf);
    }
}

}

et effectuez les opérations suivantes en XML:

 <com.packagename.CusFntTextView
        Android:id="@+id/tvtitle"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"         
        Android:text="Hi Android"           
        Android:textAppearance="?android:attr/textAppearanceLarge"
      />
15
Palani

Je suggérerais également d'étendre TextView et d'autres contrôles, mais il serait préférable que je considère la mise en place de polices dans les constructions.

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

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

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

protected void init() {
    setTypeface(Typeface.createFromAsset(getContext().getAssets(), AppConst.FONT));
}
9
Andrey Mischenko

Je voudrais améliorer les réponses de weston et Roger Huang pour l'API 21 Android Lollipop avec le thème "Theme.AppCompat".

Sous Android 4.4

<resources>
    <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
    </style>

   <!-- Application theme. -->
   <style name="AppTheme" parent="AppBaseTheme">
       <item name="Android:typeface">monospace</item>
   </style>
</resources>

Plus (égal) API 5.0

<resources>
    <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
    </style>

   <!-- Application theme. -->
   <style name="AppTheme" parent="AppBaseTheme">
       <item name="Android:textAppearance">@style/CustomTextAppearance</item>
   </style>

   <style name="CustomTextAppearance">
       <item name="Android:typeface">monospace</item>
   </style>
</resources>

Et le fichier util FontsOverride est identique à celui de la réponse de weston . J'ai testé sur ces téléphones:

Nexus 5 (système Android Android 5.1 principal) 

ZTE V5 (Android 5.1 CM12.1) 

XIAOMI note (Android 4.4 MIUI6)

HUAWEI C8850 (Android 2.3.5 UNKNOWN)

8
lovefish

Une solution brillante peut être trouvée ici: https://coderwall.com/p/qxxmaa/Android-use-a-custom-font-everywhere .

Étendez simplement les activités de BaseActivity et écrivez ces méthodes. Aussi, vous devriez mieux mettre en cache les polices comme décrit ici: https://stackoverflow.com/a/16902532/2914140 .


Après quelques recherches, j'ai écrit un code qui fonctionne sur Samsung Galaxy Tab A (Android 5.0). Code utilisé de weston et de Roger Huang ainsi que https://stackoverflow.com/a/33236102/2914140 . Également testé sur Lenovo TAB 2 A10-70L, où cela ne fonctionne pas ... J'ai inséré une police 'Comic Sans' ici pour voir une différence.

import Android.content.Context;
import Android.graphics.Typeface;
import Android.os.Build;
import Android.util.Log;
import Java.lang.reflect.Field;
import Java.util.HashMap;
import Java.util.Map;

public class FontsOverride {
    private static final int BOLD = 1;
    private static final int BOLD_ITALIC = 2;
    private static final int ITALIC = 3;
    private static final int LIGHT = 4;
    private static final int CONDENSED = 5;
    private static final int THIN = 6;
    private static final int MEDIUM = 7;
    private static final int REGULAR = 8;

    private Context context;

    public FontsOverride(Context context) {
        this.context = context;
    }

    public void loadFonts() {
        Map<String, Typeface> fontsMap = new HashMap<>();
        fontsMap.put("sans-serif", getTypeface("comic.ttf", REGULAR));
        fontsMap.put("sans-serif-bold", getTypeface("comic.ttf", BOLD));
        fontsMap.put("sans-serif-italic", getTypeface("comic.ttf", ITALIC));
        fontsMap.put("sans-serif-light", getTypeface("comic.ttf", LIGHT));
        fontsMap.put("sans-serif-condensed", getTypeface("comic.ttf", CONDENSED));
        fontsMap.put("sans-serif-thin", getTypeface("comic.ttf", THIN));
        fontsMap.put("sans-serif-medium", getTypeface("comic.ttf", MEDIUM));
        overrideFonts(fontsMap);
    }

    private void overrideFonts(Map<String, Typeface> typefaces) {
        if (Build.VERSION.SDK_INT == 21) {
            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", "Cannot set custom fonts");
            }
        } else {
            try {
                for (Map.Entry<String, Typeface> entry : typefaces.entrySet()) {
                    final Field staticField = Typeface.class.getDeclaredField(entry.getKey());
                    staticField.setAccessible(true);
                    staticField.set(null, entry.getValue());
                }
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    private Typeface getTypeface(String fontFileName, int fontType) {
        final Typeface tf = Typeface.createFromAsset(context.getAssets(), "fonts/" + fontFileName);
        return Typeface.create(tf, fontType);
    }
}

Pour exécuter le code dans toute l'application, vous devez écrire dans une classe telle qu'Application, comme suit:

    new FontsOverride(this).loadFonts();

Créez un dossier 'polices' dans 'actifs' et placez-y les polices nécessaires. Une instruction simple peut être trouvée ici: https://stackoverflow.com/a/31697103/2914140 .

Le périphérique Lenovo obtient également, à tort, la valeur d'un caractère. Dans la plupart des cas, il retourne Typeface.NORMAL, parfois NULL. Même si un TextView est en gras (dans la disposition de fichier XML). Voir ici: TextView isBold renvoie toujours NORMAL . De cette façon, un texte sur un écran est toujours dans une police de caractères normal, pas gras ni en italique. Donc, je pense que c'est un bug d'un producteur.

7
CoolMind

Travailler pour Xamarin.Android:

Classe:

public class FontsOverride
{
    public static void SetDefaultFont(Context context, string staticTypefaceFieldName, string fontAssetName)
    {
        Typeface regular = Typeface.CreateFromAsset(context.Assets, fontAssetName);
        ReplaceFont(staticTypefaceFieldName, regular);
    }

    protected static void ReplaceFont(string staticTypefaceFieldName, Typeface newTypeface)
    {
        try
        {
            Field staticField = ((Java.Lang.Object)(newTypeface)).Class.GetDeclaredField(staticTypefaceFieldName);
            staticField.Accessible = true;
            staticField.Set(null, newTypeface);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

Mise en œuvre de l'application:

namespace SomeAndroidApplication
{
    [Application]
    public class App : Application
    {
        public App()
        {

        }

        public App(IntPtr handle, JniHandleOwnership transfer)
            : base(handle, transfer)
        {

        }

        public override void OnCreate()
        {
            base.OnCreate();

            FontsOverride.SetDefaultFont(this, "MONOSPACE", "fonts/Roboto-Light.ttf");
        }
    }
}

Style:

<style name="Theme.Storehouse" parent="Theme.Sherlock">
    <item name="Android:typeface">monospace</item>
</style>
6
Guy Micciche

Depuis Android O, il est maintenant possible de définir directement à partir du XML et mon bug est maintenant fermé!

Voir ici pour plus de détails

TL; DR:

Vous devez d'abord ajouter vos polices au projet

Deuxièmement, vous ajoutez une famille de polices, comme ceci:

<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <font
        Android:fontStyle="normal"
        Android:fontWeight="400"
        Android:font="@font/lobster_regular" />
    <font
        Android:fontStyle="italic"
        Android:fontWeight="400"
        Android:font="@font/lobster_italic" />
</font-family>

Enfin, vous pouvez utiliser la police dans une mise en page ou un style:

<TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:fontFamily="@font/lobster"/>

<style name="customfontstyle" parent="@Android:style/TextAppearance.Small">
    <item name="Android:fontFamily">@font/lobster</item>
</style>

Prendre plaisir!

5
Sam

Vous pouvez définir des polices personnalisées pour chaque mise en page, une par une, avec un seul appel de fonction à partir de chaque mise en page en transmettant sa racine View. Tout d'abord, créez une approche unique pour accéder à un objet de police comme celui-ci. 

 public class Font {
    private static Font font;
    public Typeface ROBO_LIGHT;

    private Font() {

    }

    public static Font getInstance(Context context) {
        if (font == null) {
            font = new Font();
            font.init(context);
        }
        return font;

    }

    public void init(Context context) {

        ROBO_LIGHT = Typeface.createFromAsset(context.getAssets(),
                "Roboto-Light.ttf");
    }

}

Vous pouvez définir différentes polices dans la classe ci-dessus. Définissez maintenant une classe d'assistance de police qui appliquera les polices: 

   public class FontHelper {

    private static Font font;

    public static void applyFont(View parentView, Context context) {

        font = Font.getInstance(context);

        apply((ViewGroup)parentView);

    }

    private static void apply(ViewGroup parentView) {
        for (int i = 0; i < parentView.getChildCount(); i++) {

            View view = parentView.getChildAt(i);

//You can add any view element here on which you want to apply font 

            if (view instanceof EditText) {

                ((EditText) view).setTypeface(font.ROBO_LIGHT);

            }
            if (view instanceof TextView) {

                ((TextView) view).setTypeface(font.ROBO_LIGHT);

            }

            else if (view instanceof ViewGroup
                    && ((ViewGroup) view).getChildCount() > 0) {
                apply((ViewGroup) view);
            }

        }

    }

}

Dans le code ci-dessus, j'applique des polices sur textView et EditText uniquement. Vous pouvez également appliquer des polices sur d'autres éléments de vue de la même manière. Il vous suffit de passer l'identifiant de votre groupe View racine à la méthode de police d'application ci-dessus. Par exemple, votre mise en page est:

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical"
    Android:id="@+id/mainParent"
    tools:context="${relativePackage}.${activityClass}" >

    <RelativeLayout
        Android:id="@+id/mainContainer"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_above="@+id/homeFooter"
        Android:layout_below="@+id/edit" >

        <ImageView
            Android:id="@+id/PreviewImg"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:src="@drawable/abc_list_longpressed_holo"
            Android:visibility="gone" />

        <RelativeLayout
            Android:id="@+id/visibilityLayer"
            Android:layout_width="match_parent"
            Android:layout_height="fill_parent" >

            <ImageView
                Android:id="@+id/UseCamera"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:layout_alignParentTop="true"
                Android:layout_centerHorizontal="true"
                Android:src="@drawable/camera" />

            <TextView
                Android:id="@+id/tvOR"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:layout_below="@+id/UseCamera"
                Android:layout_centerHorizontal="true"
                Android:layout_marginTop="20dp"
                Android:text="OR"
                Android:textSize="30dp" />

            <TextView
                Android:id="@+id/tvAND"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:layout_centerHorizontal="true"
                Android:layout_marginTop="20dp"
                Android:text="OR"
                Android:textSize="30dp" />

</RelativeLayout>

Dans la mise en page ci-dessus, l’id du parent racine est "Parent principal", permet maintenant d’appliquer la police de caractères. 

public class MainActivity extends BaseFragmentActivity {

    private EditText etName;
    private EditText etPassword;
    private TextView tvTitle;
    public static boolean isHome = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

       Font font=Font.getInstance(getApplicationContext());
        FontHelper.applyFont(findViewById(R.id.mainParent),          getApplicationContext());
   }    
}

À votre santé :) 

4
Ajji

Je suggèrerais d'étendre TextView et d'utiliser toujours votre TextView personnalisé dans vos mises en page XML ou partout où vous avez besoin d'un TextView. Dans votre TextView personnalisé, remplacez setTypeface

@Override
public void setTypeface(Typeface tf, int style) {
    //to handle bold, you could also handle italic or other styles here as well
    if (style == 1){
        tf = Typeface.createFromAsset(getContext().getApplicationContext().getAssets(), "MuseoSans700.otf");
    }else{
        tf = Typeface.createFromAsset(getContext().getApplicationContext().getAssets(), "MuseoSans500.otf");
    }
    super.setTypeface(tf, 0);
}
3
Sam Dozor

J'ai écrit une classe affectant un caractère aux vues de la hiérarchie de vues actuelle et basé sur ses propriétés (gras, normal, vous pouvez ajouter d'autres styles si vous le souhaitez):

public final class TypefaceAssigner {

public final Typeface DEFAULT;
public final Typeface DEFAULT_BOLD;

@Inject
public TypefaceAssigner(AssetManager assetManager) {
    DEFAULT = Typeface.createFromAsset(assetManager, "TradeGothicLTCom.ttf");
    DEFAULT_BOLD = Typeface.createFromAsset(assetManager, "TradeGothicLTCom-Bd2.ttf");
}

public void assignTypeface(View v) {
    if (v instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) v).getChildCount(); i++) {
            View view = ((ViewGroup) v).getChildAt(i);
            if (view instanceof ViewGroup) {
                setTypeface(view);
            } else {
                setTypeface(view);
            }
        }
    } else {
        setTypeface(v);
    }
}

private void setTypeface(View view) {
    if (view instanceof TextView) {
        TextView textView = (TextView) view;
        Typeface typeface = textView.getTypeface();
        if (typeface != null && typeface.isBold()) {
            textView.setTypeface(DEFAULT_BOLD);
        } else {
            textView.setTypeface(DEFAULT);
        }
    }
}
}

Désormais, dans tous les fragments dans onViewCreated ou onCreateView, dans toutes les activités dans onCreate et dans tous les adaptateurs de vue dans getView ou newView, il suffit d'appeler:

typefaceAssigner.assignTypeface(view);
2
Ivan Kravchenko

La solution de Tom fonctionne très bien, mais ne fonctionne qu'avec TextView et EditText.

Si vous voulez couvrir la plupart des vues (RadioGroup, TextView, Checkbox ...), j'ai créé une méthode faisant cela: 

protected void changeChildrenFont(ViewGroup v, Typeface font){
    for(int i = 0; i < v.getChildCount(); i++){

        // For the ViewGroup, we'll have to use recursivity
        if(v.getChildAt(i) instanceof ViewGroup){
            changeChildrenFont((ViewGroup) v.getChildAt(i), font);
        }
        else{
            try {
                Object[] nullArgs = null;
                //Test wether setTypeface and getTypeface methods exists
                Method methodTypeFace = v.getChildAt(i).getClass().getMethod("setTypeface", new Class[] {Typeface.class, Integer.TYPE});
                //With getTypefaca we'll get back the style (Bold, Italic...) set in XML
                Method methodGetTypeFace = v.getChildAt(i).getClass().getMethod("getTypeface", new Class[] {});
                Typeface typeFace = ((Typeface)methodGetTypeFace.invoke(v.getChildAt(i), nullArgs));
                //Invoke the method and apply the new font with the defined style to the view if the method exists (textview,...)
                methodTypeFace.invoke(v.getChildAt(i), new Object[] {font, typeFace == null ? 0 : typeFace.getStyle()});
            }
            //Will catch the view with no such methods (listview...)
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Cette méthode récupère le style de la vue définie en XML (gras, italique ...) et les applique si elles existent. 

Pour ListView, je crée toujours un adaptateur et je règle la police dans getView. 

2
FR073N

Enfin, Google a pris conscience de la gravité de ce problème (application de polices personnalisées aux composants de l'interface utilisateur) et a mis au point une solution propre à ce problème.

Tout d'abord, vous devez effectuer une mise à jour pour prendre en charge la bibliothèque 26+ (vous devrez peut-être également mettre à jour votre diplômé {4.0+}, Android Studio), puis vous pourrez créer un nouveau dossier de ressources appelé police. Dans ce dossier, vous pouvez placer vos ressources de police (.tff, ...) . Vous devez ensuite remplacer l'application par défaut et y forcer votre police personnalisée :)

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="Android:fontFamily">@font/my_custom_font</item>
</style>

Remarque: si vous souhaitez prendre en charge des appareils dotés d'une API plus ancienne que 16, vous devez utiliser un espace de noms d'applications au lieu d'Android! 

1
Mr.Q

dans api 26 avec build.gradle 3.0.0 et supérieur, vous pouvez créer un répertoire de polices dans res .__ et utiliser cette ligne dans votre style

<item name="Android:fontFamily">@font/your_font</item>

for change build.gradle, utilisez-le dans vos dépendances build.gradle

classpath 'com.Android.tools.build:gradle:3.0.0'

J'aimerais également améliorer la réponse de Weston pour API 21 Android 5.0.

J'ai eu le même problème sur mon Samsung S5, lors de l'utilisation de la police DEFAULT. (avec les autres polices ça marche bien)

J'ai réussi à le faire fonctionner en définissant le typeface ("sans" par exemple) dans les fichiers XML, pour chaque Textview ou Button

<TextView
Android:layout_width="match_parent"
Android:layout_height="39dp"
Android:textColor="@color/abs__background_holo_light"
Android:textSize="12sp"
Android:gravity="bottom|center"
Android:typeface="sans" />

et dans MyApplication Class:

public class MyApplication extends Application {
    @Override
    public void onCreate() {
    TypefaceUtil.overrideFont(getApplicationContext(), "SANS_SERIF",
    "fonts/my_font.ttf");
    }
}

J'espère que ça aide.

0
stevenwood

Pour changer la famille de polices par défaut de TextViews, remplacez textViewStyle dans le thème de votre application.

Pour utiliser une police personnalisée dans fontFamily, utilisez les ressources de police disponibles dans la bibliothèque de support. 

La fonctionnalité a été ajoutée dans Android 26 mais rétroportée dans les anciennes versions via supportlib.

https://developer.Android.com/guide/topics/resources/font-resource.htmlhttps://developer.Android.com/guide/topics/ui/look-and- feel/fonts-in-xml.html # using-support-lib

0
Siyamed

La calligraphie fonctionne assez bien, mais elle ne me convient pas car elle ne prend pas en charge différents poids (gras, italique, etc.) pour une famille de polices.

J'ai donc essayé Fontain , qui vous permet de définir des vues personnalisées et de les appliquer à des familles de polices personnalisées.

pour utiliser Fontain, vous devez ajouter les éléments suivants à votre module d'application build.gradle:

compile 'com.scopely:fontain:1.0.0'

Ensuite, au lieu d’utiliser TextView standard, vous devez utiliser FontTextView.

Exemple de FontTextView avec contenu majuscule et gras:

 <com.scopely.fontain.views.FontTextView
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:background="@Android:color/black"
            Android:textColor="@Android:color/white"
            Android:textSize="11dp"
            Android:gravity="center"
            Android:id="@+id/tv1"
            app:font_family="myCustomFont"
            app:caps_mode="characters"
            app:font_weight="BOLD"/>
0
Cris

Depuis la sortie d'Android Oreo et de sa bibliothèque de support (26.0.0), vous pouvez le faire facilement. Reportez-vous à cette réponse dans une autre question.

En gros, votre style final ressemblera à ceci:

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
   <item name="fontFamily">@font/your_font</item> <!-- target Android sdk versions < 26 and > 14 -->
</style>
0
João Magalhães

Cette solution ne fonctionne pas correctement dans certaines situations.
Je l’étends donc:

PolicesReplacer.Java

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        FontsReplacer.replaceFonts(this);
        super.onCreate();
    }

}

https://Gist.github.com/orwir/6df839e3527647adc2d56bfadfaad805

0
Igor
package com.theeasylearn.demo.designdemo;
import Android.content.Context;
import Android.graphics.Typeface;
import Android.util.AttributeSet;
import Android.widget.TextView;

public class MyButton extends TextView {

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

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

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

    private void init() {

            Typeface tf =
                    Typeface.createFromAsset(
                            getContext().getAssets(), "angelina.TTF");
            setTypeface(tf);

    }

}
0