Android: vous souhaitez définir des polices personnalisées pour l'ensemble de l'application et non pour l'exécution

100

Est-il possible de définir une police personnalisée dans chaque contrôle de l'application? Et pas nécessairement runtime? (c'est-à-dire à partir de xml si possible ou une seule fois pour toute l'application dans un fichier JAVA)

Je peux définir la police pour un contrôle à partir de ce code.

public static void setFont(TextView textView) {
    Typeface tf = Typeface.createFromAsset(textView.getContext()
            .getAssets(), "fonts/BPreplay.otf");

    textView.setTypeface(tf);

}

Et le problème avec ce code est qu'il devrait être appelé pour chaque contrôle. Et je veux appeler cette méthode ou toute autre méthode similaire une fois, ou si possible définir la propriété en xml. C'est possible?

Prasham
la source
6
Peut-être que vous pouvez écrire un contrôle personnalisé en étendant le TextView et en définissant la police dans le constructeur peut être une option, alors vous pouvez utiliser ce contrôle dans toute l'application à la place de votre textview. également pour économiser de la mémoire, vous pouvez empêcher le chargement de ressources en utilisant un type de police statique.
Varun
@Varun: eh bien, cette idée peut me faire gagner du temps, mais je dois définir chaque contrôle, et écrire un contrôle personnalisé pour chacun sera un moyen plus long que de définir un runtime de police, qu'en pensez-vous? (Cependant +1 pour l'écriture du contrôle personnalisé)
Prasham
Vous souhaiterez peut-être écrire un seul contrôle personnalisé étendant le textView et la seule modification concernera la définition de la police. En utilisant le contrôle cusotm dans vos fichiers de mise en page, vous n'avez pas à le faire manuellement chaque fois pour chaque vue de texte et vous pouvez toujours être assuré que vous utilisez la police que vous voulez.
Varun
Qu'en est-il d'écrire une coutume VIEWau lieu d'écrire un custom text viewet un custom button viewséparément? Mon exigence concerne chaque contrôle, et la vue texte n'était qu'un exemple. Désolé, j'ai oublié de le mentionner .. :-(
Prasham
1
Jetez un oeil sur la question satckoverflow stackoverflow.com/questions/2711858/… cela vous aide.
Ashwini

Réponses:

123

EDIT : Cela fait donc un moment, et j'aimerais ajouter ce que je pense être la meilleure façon de le faire, et par XML pas moins!

Donc, tout d'abord, vous allez vouloir créer une nouvelle classe qui remplace la vue que vous souhaitez personnaliser. (par exemple, vous voulez un bouton avec une police de caractères personnalisée? Étendre Button). Faisons un exemple:

public class CustomButton extends Button {
    private final static int ROBOTO = 0;
    private final static int ROBOTO_CONDENSED = 1;

    public CustomButton(Context context) {
        super(context);
    }

    public CustomButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        parseAttributes(context, attrs); //I'll explain this method later
    }

    public CustomButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        parseAttributes(context, attrs);
    }
}

Maintenant, si vous n'en avez pas, ajoutez un document XML sous res/values/attrs.xmlet ajoutez:

<resources>
    <!-- Define the values for the attribute -->
    <attr name="typeface" format="enum">
        <enum name="roboto" value="0"/>
        <enum name="robotoCondensed" value="1"/>
    </attr>

    <!-- Tell Android that the class "CustomButton" can be styled, 
         and which attributes it supports -->
    <declare-styleable name="CustomButton">
        <attr name="typeface"/>
    </declare-styleable>
</resources>

D'accord, donc avec cela à l'écart, revenons à la parseAttributes()méthode précédente:

private void parseAttributes(Context context, AttributeSet attrs) {
    TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.CustomButton);

    //The value 0 is a default, but shouldn't ever be used since the attr is an enum
    int typeface = values.getInt(R.styleable.CustomButton_typeface, 0);

    switch(typeface) {
        case ROBOTO: default:
            //You can instantiate your typeface anywhere, I would suggest as a 
            //singleton somewhere to avoid unnecessary copies
            setTypeface(roboto); 
            break;
        case ROBOTO_CONDENSED:
            setTypeface(robotoCondensed);
            break;
    }

    values.recycle();
}

Maintenant, vous êtes prêt. Vous pouvez ajouter plus d'attributs pour à peu près tout (vous pouvez en ajouter un autre pour typefaceStyle - gras, italique, etc.) mais voyons maintenant comment l'utiliser:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/com.yourpackage.name"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <com.yourpackage.name.CustomButton
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click Me!"
        custom:typeface="roboto" />

</LinearLayout>

La xmlns:customligne peut vraiment être n'importe quoi, mais la convention est celle illustrée ci-dessus. Ce qui compte, c'est qu'il soit unique, et c'est pourquoi le nom du package est utilisé. Maintenant, vous utilisez simplement le custom:préfixe pour vos attributs et le android:préfixe pour les attributs Android.

Une dernière chose: si vous voulez utiliser ceci dans un style ( res/values/styles.xml), vous ne devez pas ajouter la xmlns:customligne. Faites simplement référence au nom de l'attribut sans préfixe:

<style name="MyStyle>
    <item name="typeface">roboto</item>
</style>

                               (PREVIOUS ANSWER)

Utilisation d'une police personnalisée sous Android

Cela devrait aider. Fondamentalement, il n'y a aucun moyen de le faire en XML, et pour autant que je sache, pas de moyen plus simple de le faire dans le code. Vous pouvez toujours avoir une méthode setLayoutFont () qui crée la police une fois, puis exécute setTypeface () pour chacune. Il vous suffit de le mettre à jour chaque fois que vous ajoutez un nouvel élément à une mise en page. Quelque chose comme ci-dessous:

public void setLayoutFont() {
    Typeface tf = Typeface.createFromAsset(
        getBaseContext().getAssets(), "fonts/BPreplay.otf");
    TextView tv1 = (TextView)findViewById(R.id.tv1);
    tv1.setTypeface(tf);

    TextView tv2 = (TextView)findViewById(R.id.tv2);
    tv2.setTypeface(tf);

    TextView tv3 = (TextView)findViewById(R.id.tv3);
    tv3.setTypeface(tf);
}

EDIT : Donc je me suis mis à implémenter moi-même quelque chose comme ça, et comment j'ai fini par le faire était de créer une fonction comme celle-ci:

public static void setLayoutFont(Typeface tf, TextView...params) {
    for (TextView tv : params) {
        tv.setTypeface(tf);
    }
}

Ensuite, utilisez simplement cette méthode de onCreate () et transmettez tous les TextViews que vous souhaitez mettre à jour:

Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/BPreplay.otf");
//find views by id...
setLayoutFont(tf, tv1, tv2, tv3, tv4, tv5);

MODIFIER 9/5/12:

Donc, comme cela continue de recevoir des vues et des votes, j'aimerais ajouter une méthode bien meilleure et plus complète:

Typeface mFont = Typeface.createFromAsset(getAssets(), "fonts/BPreplay.otf");
ViewGroup root = (ViewGroup)findViewById(R.id.myrootlayout);
setFont(root, mFont);

/*
 * Sets the font on all TextViews in the ViewGroup. Searches
 * recursively for all inner ViewGroups as well. Just add a
 * check for any other views you want to set as well (EditText,
 * etc.)
 */
public void setFont(ViewGroup group, Typeface font) {
    int count = group.getChildCount();
    View v;
    for(int i = 0; i < count; i++) {
        v = group.getChildAt(i);
        if(v instanceof TextView || v instanceof Button /*etc.*/)
            ((TextView)v).setTypeface(font);
        else if(v instanceof ViewGroup)
            setFont((ViewGroup)v, font);
    }
}

Si vous lui passez la racine de votre mise en page, il recherchera récursivement TextViewou Buttonvues (ou toute autre que vous ajoutez à cette instruction if) dans cette mise en page, et définira la police sans que vous ayez à les spécifier par ID. Cela suppose bien sûr que vous souhaitez définir la police pour chaque vue.

Kevin Coppock
la source
1
Je ne vois aucune différence dans votre code et mon code sauf que j'utilise la méthode comme méthode d'usine pour l'ensemble de l'application et que votre code semble être écrit pour une activité. PS, il est vraiment étrange d'ajouter un objet supplémentaire pour un textView en lecture seule juste pour changer la police. Hors sujet: Android devrait vraiment introduire un mécanisme pour récupérer une police dans le dossier assests et pour être incluse dans R afin qu'elle puisse être modifiée au moment de la conception)
Prasham
1
Je suppose que de manière réaliste, il n'y a pas de différence majeure à part le fait que vous ne créeriez pas la police encore et encore. L'idée de Varun d'utiliser simplement une police statique ferait la même chose.
Kevin Coppock
1
Si la dernière ligne de votre exemple de code doit être setLayoutFont (tf, tv1, tv2, tv3, tv4, tv5); plutôt que setTypeface (tf, tv1, tv2, tv3, tv4, tv5) ;?
Kyle Clegg
1
Ne devriez-vous pas recyclele TypedArray values?
CorayJeu
1
Si vous utilisez Gradle, l'espace de noms personnalisé doit êtrexmlns:custom="http://schemas.android.com/apk/res-auto"
Jabari
93

Il existe un moyen assez simple de le faire via XML. Il vous suffit de créer votre propre widget qui étend TextView.

Tout d'abord, créez un fichier dans res / values ​​/ attrs.xml avec le contenu suivant:

<resources>
    <declare-styleable name="TypefacedTextView">
        <attr name="typeface" format="string" />
    </declare-styleable>
</resources>

Après cela, créez votre widget personnalisé:

package your.package.widget;

public class TypefacedTextView extends TextView {

    public TypefacedTextView(Context context, AttributeSet attrs) {
        super(context, attrs);

        //Typeface.createFromAsset doesn't work in the layout editor. Skipping...
        if (isInEditMode()) {
            return;
        }

        TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.TypefacedTextView);
        String fontName = styledAttrs.getString(R.styleable.TypefacedTextView_typeface);
        styledAttrs.recycle();

        if (fontName != null) {
            Typeface typeface = Typeface.createFromAsset(context.getAssets(), fontName);
            setTypeface(typeface);
        }
    }

}

Comme vous pouvez le voir, le code ci-dessus lira une police dans le dossier assets /. Pour cet exemple, je suppose qu'il existe un fichier appelé "custom.ttf" dans le dossier des actifs. Enfin, utilisez le widget dans les XML:

<your.package.widget.TypefacedTextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:your_namespace="http://schemas.android.com/apk/res/your.package"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Custom fonts in XML are easy"
    android:textColor="#FFF"
    android:textSize="14dip"
    your_namespace:typeface="custom.ttf" />

Remarque: vous ne pourrez pas voir votre police personnalisée dans l'éditeur de mise en page d'Eclipse. C'est pourquoi j'ai mis le isInEditMode()chèque. Mais si vous exécutez votre application, la police personnalisée fonctionnera comme un charme.

J'espère que ça aide!

léocadiotine
la source
Je n'ai pas essayé cela, mais j'ai créé un contrôle personnalisé en étendant la TextViewclasse; mis le typefacededans et utilisé le contrôle personnalisé dans la mise en page comme nous le faisons normalement et cela a fonctionné pour moi ... C'était simple, cependant, que celui ci-dessus ...
Mahendra Liya
1
J'ai fait exactement ce que tu as dit. La seule différence est que j'ai rendu ce composant réutilisable, car la question demande comment faire cela via XML. Il existe en effet un moyen de le faire via XML et c'est le moyen de le faire :)
leocadiotine
Code très facile à intégrer. Ça marche pour moi. Merci.
Durai
1
Celui-ci devrait être la réponse acceptée. Joliment écrit. Merci!
Reaz Murshed
1
Amesome, @DominikSuszczewicz! Pouvez-vous s'il vous plaît partager le code afin que je puisse mettre à jour la réponse?
léocadiotine
15

Exemple de TextView avec la police roboto:

attr.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

<declare-styleable name="RobotoTextView">
    <attr name="typeface"/>
</declare-styleable>

<attr name="typeface" format="enum">
    <enum name="roboto_thin" value="0"/>
    <enum name="roboto_thin_italic" value="1"/>
    <enum name="roboto_light" value="2"/>
    <enum name="roboto_light_italic" value="3"/>
    <enum name="roboto_regular" value="4"/>
    <enum name="roboto_italic" value="5"/>
    <enum name="roboto_medium" value="6"/>
    <enum name="roboto_medium_italic" value="7"/>
    <enum name="roboto_bold" value="8"/>
    <enum name="roboto_bold_italic" value="9"/>
    <enum name="roboto_black" value="10"/>
    <enum name="roboto_black_italic" value="11"/>
    <enum name="roboto_condensed" value="12"/>
    <enum name="roboto_condensed_italic" value="13"/>
    <enum name="roboto_condensed_bold" value="14"/>
    <enum name="roboto_condensed_bold_italic" value="15"/>
</attr>

</resources>

RobotoTextView.java:

public class RobotoTextView extends TextView {

/*
 * Permissible values ​​for the "typeface" attribute.
 */
private final static int ROBOTO_THIN = 0;
private final static int ROBOTO_THIN_ITALIC = 1;
private final static int ROBOTO_LIGHT = 2;
private final static int ROBOTO_LIGHT_ITALIC = 3;
private final static int ROBOTO_REGULAR = 4;
private final static int ROBOTO_ITALIC = 5;
private final static int ROBOTO_MEDIUM = 6;
private final static int ROBOTO_MEDIUM_ITALIC = 7;
private final static int ROBOTO_BOLD = 8;
private final static int ROBOTO_BOLD_ITALIC = 9;
private final static int ROBOTO_BLACK = 10;
private final static int ROBOTO_BLACK_ITALIC = 11;
private final static int ROBOTO_CONDENSED = 12;
private final static int ROBOTO_CONDENSED_ITALIC = 13;
private final static int ROBOTO_CONDENSED_BOLD = 14;
private final static int ROBOTO_CONDENSED_BOLD_ITALIC = 15;
/**
 * List of created typefaces for later reused.
 */
private final static SparseArray<Typeface> mTypefaces = new SparseArray<Typeface>(16);

/**
 * Simple constructor to use when creating a view from code.
 *
 * @param context The Context the view is running in, through which it can
 *                access the current theme, resources, etc.
 */
public RobotoTextView(Context context) {
    super(context);
}

/**
 * Constructor that is called when inflating a view from XML. This is called
 * when a view is being constructed from an XML file, supplying attributes
 * that were specified in the XML file. This version uses a default style of
 * 0, so the only attribute values applied are those in the Context's Theme
 * and the given AttributeSet.
 * <p/>
 * <p/>
 * The method onFinishInflate() will be called after all children have been
 * added.
 *
 * @param context The Context the view is running in, through which it can
 *                access the current theme, resources, etc.
 * @param attrs   The attributes of the XML tag that is inflating the view.
 * @see #RobotoTextView(Context, AttributeSet, int)
 */
public RobotoTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    parseAttributes(context, attrs);
}

/**
 * Perform inflation from XML and apply a class-specific base style. This
 * constructor of View allows subclasses to use their own base style when
 * they are inflating.
 *
 * @param context  The Context the view is running in, through which it can
 *                 access the current theme, resources, etc.
 * @param attrs    The attributes of the XML tag that is inflating the view.
 * @param defStyle The default style to apply to this view. If 0, no style
 *                 will be applied (beyond what is included in the theme). This may
 *                 either be an attribute resource, whose value will be retrieved
 *                 from the current theme, or an explicit style resource.
 * @see #RobotoTextView(Context, AttributeSet)
 */
public RobotoTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    parseAttributes(context, attrs);
}

/**
 * Parse the attributes.
 *
 * @param context The Context the view is running in, through which it can access the current theme, resources, etc.
 * @param attrs   The attributes of the XML tag that is inflating the view.
 */
private void parseAttributes(Context context, AttributeSet attrs) {
    TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.RobotoTextView);

    int typefaceValue = values.getInt(R.styleable.RobotoTextView_typeface, 0);
    values.recycle();

    setTypeface(obtaintTypeface(context, typefaceValue));
}

/**
 * Obtain typeface.
 *
 * @param context       The Context the view is running in, through which it can
 *                      access the current theme, resources, etc.
 * @param typefaceValue values ​​for the "typeface" attribute
 * @return Roboto {@link Typeface}
 * @throws IllegalArgumentException if unknown `typeface` attribute value.
 */
private Typeface obtaintTypeface(Context context, int typefaceValue) throws IllegalArgumentException {
    Typeface typeface = mTypefaces.get(typefaceValue);
    if (typeface == null) {
        typeface = createTypeface(context, typefaceValue);
        mTypefaces.put(typefaceValue, typeface);
    }
    return typeface;
}

/**
 * Create typeface from assets.
 *
 * @param context       The Context the view is running in, through which it can
 *                      access the current theme, resources, etc.
 * @param typefaceValue values ​​for the "typeface" attribute
 * @return Roboto {@link Typeface}
 * @throws IllegalArgumentException if unknown `typeface` attribute value.
 */
private Typeface createTypeface(Context context, int typefaceValue) throws IllegalArgumentException {
    Typeface typeface;
    switch (typefaceValue) {
        case ROBOTO_THIN:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Thin.ttf");
            break;
        case ROBOTO_THIN_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-ThinItalic.ttf");
            break;
        case ROBOTO_LIGHT:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Light.ttf");
            break;
        case ROBOTO_LIGHT_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-LightItalic.ttf");
            break;
        case ROBOTO_REGULAR:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Regular.ttf");
            break;
        case ROBOTO_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Italic.ttf");
            break;
        case ROBOTO_MEDIUM:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Medium.ttf");
            break;
        case ROBOTO_MEDIUM_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-MediumItalic.ttf");
            break;
        case ROBOTO_BOLD:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Bold.ttf");
            break;
        case ROBOTO_BOLD_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldItalic.ttf");
            break;
        case ROBOTO_BLACK:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Black.ttf");
            break;
        case ROBOTO_BLACK_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BlackItalic.ttf");
            break;
        case ROBOTO_CONDENSED:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Condensed.ttf");
            break;
        case ROBOTO_CONDENSED_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-CondensedItalic.ttf");
            break;
        case ROBOTO_CONDENSED_BOLD:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldCondensed.ttf");
            break;
        case ROBOTO_CONDENSED_BOLD_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldCondensedItalic.ttf");
            break;
        default:
            throw new IllegalArgumentException("Unknown `typeface` attribute value " + typefaceValue);
    }
    return typeface;
}

}

Exemple d'utilisation:

<your.package.widget.RobotoTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:typeface="roboto_thin"
                android:textSize="22sp"
                android:text="Roboto Thin"/>

Ressources: polices Roboto & Noto

e.shishkin
la source
existe-t-il un moyen d'utiliser cette solution cependant sans fixer les identifiants des polices dans la classe java? peut-être lire ces champs finaux depuis enum attrs .. private final static int ROBOTO_THIN = 0; int statique final privé ROBOTO_THIN_ITALIC = 1; int statique final privé ROBOTO_LIGHT = 2; ...
Arthur Melo
3

Il est trop tard mais cela aide l'autre,
j'ai créé CustomTextView qui a un attribut appelé typeFace et s'occupe du problème de fuite de mémoire avec le chargement de la police sans mise en cache

Première Fontsclasse qui charge les polices des actifs pour une seule fois

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

import java.util.Hashtable;

/**
 * Created by tonyhaddad on 7/19/15.
 */
public class Fonts {
    private Context context;

    public Fonts(Context context) {
        this.context = context;
    }
    private static Hashtable<String, Typeface> sTypeFaces = new Hashtable<String, Typeface>(
            4);
    public static Typeface getTypeFace(Context context, String fileName) {
        Typeface tempTypeface = sTypeFaces.get(fileName);

        if (tempTypeface == null) {
            String fontPath=null;
            if(fileName=="metabold")
                fontPath ="fonts/Meta-Bold.ttf";

            else if(fileName=="metanormal")
                fontPath="fonts/Meta-Normal.ttf";
            else if(fileName=="gsligh")
                fontPath="fonts/gesslight.ttf";
            else if(fileName=="bold")
                fontPath="fonts/Lato-Bold.ttf";
            else if(fileName=="rcr")
                fontPath="fonts/RobotoCondensed-Regular.ttf";

            else if(fileName=="mpr")
                fontPath="fonts/MyriadPro-Regular.otf";
            else if(fileName=="rr")
                fontPath="fonts/Roboto-Regular.ttf";

            tempTypeface = Typeface.createFromAsset(context.getAssets(), fontPath);
            sTypeFaces.put(fileName, tempTypeface);
        }

        return tempTypeface;
    }
}

alors vous devez ajouter un attribut personnalisé dans le fichier attrs.xml ajoutez ceci

<declare-styleable name="CustomFontTextView">
        <attr name="typeFace" format="string" />

    </declare-styleable>

puis classe personnalisée

 package package_name;

/**
 * Created by tonyhaddad on 8/26/15.
 */

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;

import package_name.R;

public class CustomFontTextView extends TextView {

    String typeFace;


    public CustomFontTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        if (isInEditMode()) {
            return;
        }
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CustomFontTextView,
                0, 0);
        try {
            typeFace = a.getString(0);
        } finally {
            a.recycle();
        }

        if(typeFace!=null && !typeFace.equalsIgnoreCase(""))
        {
            Typeface tf = Fonts.getTypeFace(context, typeFace);
            setTypeface(tf);
        }
        init();
    }

    public CustomFontTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        if (isInEditMode()) {
            return;
        }
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CustomFontTextView,
                0, 0);
        try {
            typeFace = a.getString(0);
        } finally {
            a.recycle();
        }

        if(typeFace!=null && !typeFace.equalsIgnoreCase(""))
        {
            Typeface tf = Fonts.getTypeFace(context, typeFace);
            setTypeface(tf);
        }

        init();
    }

    public CustomFontTextView(Context context) {
        super(context);



        if(typeFace!=null && !typeFace.equalsIgnoreCase(""))
        {
            Typeface tf = Fonts.getTypeFace(context, typeFace);
            setTypeface(tf);
        }
        init();
    }


    private void init() {

    }

    public String getTypeFace() {
        return typeFace;
    }

    public void setTypeFace(String typeFace) {
        this.typeFace = typeFace;
        invalidate();
        requestLayout();
    }
}

et enfin ajouter la vue texte

  <package_name.CustomFontTextView
            xmlns:custom="http://schemas.android.com/apk/res-auto/package_name"
            android:id="@+id/txt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="41dp"
            android:gravity="center_vertical"
            android:text="text"
            android:textColor="#000"
            android:textSize="23sp"
            custom:typeFace="metanormal"/>

et vous pouvez modifier la police de manière progressive avec la méthode setTypeFace,
vous pouvez également déplacer l'espace de noms personnalisé vers votre mise en page parent si vous souhaitez en utiliser plusieurs à partir de cette vue

Bon codage :)

Antwan
la source
réponse stratight simple.
eyadMhanna
2

La méthode ci-dessous, appelée onCreate () et transmise à votre ViewGroup le plus à l'extérieur, fonctionnera pour tout sauf le texte créé dynamiquement (c'est-à-dire les listes dynamiques, les alertes, etc.). Un moyen simple d'obtenir le ViewGroup le plus externe consiste à utiliser getRootView sur l'une de vos vues.

public void onCreate(Bundle savedInstanceState){
    //onCreate code...
    EditText text = (EditText) findViewById(R.id.editText1);
    setTypeFaceForViewGroup((ViewGroup) text.getRootView());
}

private void setTypeFaceForViewGroup(ViewGroup vg){

    for (int i = 0; i < vg.getChildCount(); i++) {

            if (vg.getChildAt(i) instanceof ViewGroup)
                setTypeFaceForViewGroup((ViewGroup) vg.getChildAt(i));

            else if (vg.getChildAt(i) instanceof TextView)
                ((TextView) vg.getChildAt(i)).setTypeface(Typeface.createFromAsset(getAssets(), "fonts/Your_Font.ttf"));

    }

}

Cela devrait également fonctionner pour le contenu dynamique, il vous suffit de l'appeler, en passant ce que vous avez créé, juste après l'avoir créé (je ne l'ai pas testé, cependant).

Pour économiser de la mémoire, vous voudrez probablement faire de la police une variable statique, plutôt que d'en créer une nouvelle chaque fois que la boucle s'exécute comme je l'ai fait ici.

Chris
la source
Je ne recommande pas cette solution, car vous créez une nouvelle instance de la même police pour chaque élément auquel vous souhaitez l'appliquer. Cela peut entraîner des problèmes de mémoire.
flawyte
C'est couvert dans ma note à la fin.
Chris
2

Si vous recherchez une solution de programmation plus générale, j'ai créé une classe statique qui peut être utilisée pour définir la police de caractères d'une vue entière (interface utilisateur d'activité). Notez que je travaille avec Mono (C #) mais vous pouvez l'implémenter facilement en utilisant Java.

Vous pouvez transmettre à cette classe une mise en page ou une vue spécifique que vous souhaitez personnaliser. Si vous voulez être super efficace, vous pouvez l'implémenter en utilisant le modèle Singleton.

public static class AndroidTypefaceUtility 
{
    static AndroidTypefaceUtility()
    {
    }
    //Refer to the code block beneath this one, to see how to create a typeface.
    public static void SetTypefaceOfView(View view, Typeface customTypeface)
    {
    if (customTypeface != null && view != null)
    {
            try
            {
                if (view is TextView)
                    (view as TextView).Typeface = customTypeface;
                else if (view is Button)
                    (view as Button).Typeface = customTypeface;
                else if (view is EditText)
                    (view as EditText).Typeface = customTypeface;
                else if (view is ViewGroup)
                    SetTypefaceOfViewGroup((view as ViewGroup), customTypeface);
                else
                    Console.Error.WriteLine("AndroidTypefaceUtility: {0} is type of {1} and does not have a typeface property", view.Id, typeof(View));
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine("AndroidTypefaceUtility threw:\n{0}\n{1}", ex.GetType(), ex.StackTrace);
                    throw ex;
                }
            }
            else
            {
                Console.Error.WriteLine("AndroidTypefaceUtility: customTypeface / view parameter should not be null");
            }
        }

        public static void SetTypefaceOfViewGroup(ViewGroup layout, Typeface customTypeface)
        {
            if (customTypeface != null && layout != null)
            {
                for (int i = 0; i < layout.ChildCount; i++)
                {
                    SetTypefaceOfView(layout.GetChildAt(i), customTypeface);
                }
            }
            else
            {
                Console.Error.WriteLine("AndroidTypefaceUtility: customTypeface / layout parameter should not be null");
            }
        }

    }

Dans votre activité, vous devrez créer un objet Typeface. Je crée le mien dans OnCreate () en utilisant un fichier .ttf placé dans mon répertoire Resources / Assets /. Assurez-vous que le fichier est marqué comme un élément Android dans ses propriétés.

protected override void OnCreate(Bundle bundle)
{               
    ...
    LinearLayout rootLayout = (LinearLayout)FindViewById<LinearLayout>(Resource.Id.signInView_LinearLayout);
    Typeface allerTypeface = Typeface.CreateFromAsset(base.Assets,"Aller_Rg.ttf");
    AndroidTypefaceUtility.SetTypefaceOfViewGroup(rootLayout, allerTypeface);
}
JCKortlang
la source
2

Malheureusement, Android ne fournit pas le moyen rapide, simple et propre que vous recherchez pour modifier la police de l'ensemble de votre application. Mais récemment, j'ai examiné cette question et créé des outils qui vous permettent de changer la police sans aucun codage (vous pouvez tout faire via xml, les styles et même les apparences de texte). Ils sont basés sur des solutions similaires comme vous le voyez dans les autres réponses ici, mais permettent une plus grande flexibilité. Vous pouvez tout lire sur ce blog et voir le projet github ici .

Voici un exemple d'application de ces outils. Mettez tous vos fichiers de polices au format assets/fonts/. Ensuite, déclarez ces polices dans un fichier xml (par exemple res/xml/fonts.xml) et chargez ce fichier au début de votre application avec TypefaceManager.initialize(this, R.xml.fonts);(par exemple, dans le onCreate de votre classe Application). Le fichier xml ressemble à ceci:

<?xml version="1.0" encoding="utf-8"?>
<familyset>

    <!-- Some Font. Can be referenced with 'someFont' or 'aspergit' -->
    <family>
        <nameset>
            <name>aspergit</name>
            <name>someFont</name>
        </nameset>
        <fileset>
            <file>Aspergit.ttf</file>
            <file>Aspergit Bold.ttf</file>
            <file>Aspergit Italic.ttf</file>
            <file>Aspergit Bold Italic.ttf</file>
        </fileset>
    </family>

    <!-- Another Font. Can be referenced with 'anotherFont' or 'bodoni' -->
    <family>
        <nameset>
            <name>bodoni</name>
            <name>anotherFont</name>
        </nameset>
        <fileset>
            <file>BodoniFLF-Roman.ttf</file>
            <file>BodoniFLF-Bold.ttf</file>
        </fileset>
    </family>

</familyset>

Vous pouvez maintenant utiliser ces polices dans votre style ou xml (à condition d'utiliser les outils que j'ai mentionnés ci-dessus), en utilisant l'élément d'interface utilisateur personnalisé com.innovattic.font.FontTextViewdans votre mise en page xml. Ci-dessous, vous pouvez voir comment appliquer une police à tous les textes de l'ensemble de votre application, simplement en modifiant res/values/styles.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">

    <!-- Application theme -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
        <item name="android:textViewStyle">@style/MyTextViewStyle</item>
    </style>

    <!-- Style to use for ALL text views (including FontTextView) -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="MyTextViewStyle" parent="@android:style/Widget.Holo.Light.TextView">
        <item name="android:textAppearance">@style/MyTextAppearance</item>
    </style>

    <!-- Text appearance to use for ALL text views (including FontTextView) -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="MyTextAppearance" parent="@android:style/TextAppearance.Holo">
        <!-- Alternatively, reference this font with the name "aspergit" -->
        <!-- Note that only our own TextView's will use the font attribute -->
        <item name="flFont">someFont</item>
        <item name="android:textStyle">bold|italic</item>
    </style>

    <!-- Alternative style, maybe for some other widget -->
    <style name="StylishFont">
        <item name="flFont">anotherFont</item>
        <item name="android:textStyle">normal</item>
    </style>

</resources>

Avec l'accompagnement res/layout/layout.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <!-- This text view is styled with the app theme -->
    <com.innovattic.font.FontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This uses my font in bold italic style" />

    <!-- This text view is styled here and overrides the app theme -->
    <com.innovattic.font.FontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:flFont="anotherFont"
        android:textStyle="normal"
        android:text="This uses another font in normal style" />

    <!-- This text view is styled with a style and overrides the app theme -->
    <com.innovattic.font.FontTextView
        style="@style/StylishFont"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This also uses another font in normal style" />

</LinearLayout>

N'oubliez pas d'appliquer le thème dans votre manifeste Android.

Jelle Fresen
la source
2

Je voudrais ajouter une note à la grande solution de leocadiotine. C'est parfait, mais lorsque vous utilisez cette vue de texte personnalisée, l'application ralentit de nombreuses fois, car elle doit accéder aux ressources chaque fois qu'une vue de texte est créée. Je suggère d'utiliser quelque chose comme le View Holder patterndans le Adapters, j'ai écrit un exemple:

public class Fonts {

    private static final Map<String, Typeface> typefaces = new HashMap<String, Typeface>();

    public static Typeface getTypeface(Context ctx, String fontName) {
        Typeface typeface = typefaces.get(fontName);
        if (typeface == null) {
            typeface = Typeface.createFromAsset(ctx.getAssets(), fontName);
            typefaces.put(fontName, typeface);
        }
        return typeface;
    } 
}

De cette manière, l'application accède aux actifs une seule fois par actif et les garde en mémoire pour d'autres besoins.

Emaborsa
la source
0

Je ne sais pas si cela change l'ensemble de l'application, mais j'ai réussi à changer certains composants qui ne pourraient autrement pas être modifiés en faisant ceci:

Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/Lucida Sans Unicode.ttf");
Typeface.class.getField("DEFAULT").setAccessible(true);
Typeface.class.getField("DEFAULT_BOLD").setAccessible(true);
Typeface.class.getField("DEFAULT").set(null, tf);
Typeface.class.getField("DEFAULT_BOLD").set(null, tf);
Richard
la source
@richard, je veux définir la police personnalisée en fonction des paramètres régionaux, pour l'exemple, je veux définir le TTF Arial chaque fois que nous utilisons les paramètres régionaux anglais, et définir le TTF gothique lorsque j'utilise le loacale coréen
Dwivedi Ji
0

J'ai trouvé des informations étape par étape sur ce lien, lien: https://github.com/jaydipumaretiya/CustomTypeface/

Il existe de nombreuses façons d'utiliser correctement la police dans Android, vous devez placer votre fichier de police dans le dossier des actifs directement sous votre main et pouvez l'utiliser au moment de l'exécution.

Un autre moyen le plus simple consiste à utiliser la bibliothèque par défaut pour définir la police dans votre fichier xml. J'ai préféré cette bibliothèque de polices de caractères personnalisée pour définir la police sur TextView, EditText, Button, CheckBox, RadioButton et AutoCompleteTextView et d'autres wedget sous Android.

Mehul Rakholiya
la source
Le lien github ne fonctionne pas.
Thomas
0

Android 8.0 (niveau d'API 26) introduit une nouvelle fonctionnalité, les polices en XML.Vous pouvez créer un fichier fontfamily et le définir dans styles.xml.

Pour ajouter des polices en tant que ressources, effectuez les étapes suivantes dans Android Studio:

1.Cliquez avec le bouton droit sur le dossier res et accédez à Nouveau> répertoire de ressources Android. La fenêtre Nouveau répertoire de ressources apparaît.

Dans la liste Type de ressource, sélectionnez la police, puis cliquez sur OK. Remarque: le nom du répertoire de ressources doit être police.

3.Ajoutez vos fichiers de polices dans le dossier de polices.

Pour créer une famille de polices, procédez comme suit:

1.Cliquez avec le bouton droit sur le dossier de polices et accédez à Nouveau> Fichier de ressources de polices. La fenêtre Nouveau fichier de ressources apparaît.

2.Entrez le nom du fichier, puis cliquez sur OK. Le nouveau XML de ressource de police s'ouvre dans l'éditeur.

3.Incluez chaque fichier de police, style et attribut de poids dans l'élément. Le code XML suivant illustre l'ajout d'attributs liés aux polices dans le code XML de ressources de polices:

<?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>

Ajout de polices au style

Ouvrez le styles.xml et définissez l'attribut fontFamily sur le fichier de police auquel vous souhaitez accéder.

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

Source: polices en XML

Développeur Android
la source