Ajouter des custom Fonts

nexusae0_robotosans_thumb

 

Ajouter les polices à notre application

Afin d’utiliser les polices TTF sur Android, il vous faudra les ajouter dans les assets. Ce dossier permet d’inclure des fichiers de toute sorte dans notre APK, ceux-ci ne seront pas “compilés”, et accessible directement via getContext().getAssets().

Nous allons créer ce dossier assets, directement dans notre dossier main/, puis nous allons y placer notre dossier font/, contenant la liste de nos polices TTF

Capture d’écran 2015-06-30 à 16.55.25

 

La seconde étape est de modifier la police d’une TextView, pour cela deux possibilités : depuis le code Java / depuis les layouts

1. Depuis le code Java

Il est possible simplement depuis votre activité / fragment de récupérer une font placée dans les assets.
Il existe une fonction nommée Typeface.createFromAsset(getAssets(), FICHIER_DE_LA_POLICE);
Si nous travaillons avec le layout suivant

layout/activity_main

<LinearLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <TextView
        android:id="@+id/text1"
        android:layout_margin="10dp"
        android:textSize="25sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Police normal" />

    <TextView
        android:id="@+id/text2"
        android:layout_margin="10dp"
        android:textSize="25sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Police personnalisée" />

    <TextView
        android:id="@+id/text3"
        android:layout_margin="10dp"
        android:textSize="25sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Police personnalisée" />

</LinearLayout>

Nous pouvons changer facilement la font de nos textview de la façon suivante :

MainActivity.java

public class MainActivity extends AppCompatActivity {

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

        TextView textView1 = (TextView) findViewById(R.id.text1);
        TextView textView2 = (TextView) findViewById(R.id.text2);
        TextView textView3 = (TextView) findViewById(R.id.text3);

        setFont(textView2,"Roboto-Light.ttf");
        setFont(textView3,"Roboto-Black.ttf");
    }

    public void setFont(TextView textView, String fontName) {
        if(fontName != null){
            try {
                Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/" + fontName);
                textView.setTypeface(typeface);
            } catch (Exception e) {
                Log.e("FONT", fontName + " not found", e);
            }
        }
    }
}

Ce qui donne le résultat suivant

device-2015-06-30-170718

2. Depuis les layouts

Une seconde méthode, ma préférée, consiste à surcharger les TextView afin de créer une version acceptant un attribut font, indiquant quelle police utiliser. Nous appellerons cette vue CustomTextView

Il faut commencer par définir un attribut font, utilisable par notre CustomTextView :

(créer le fichier attrs.xml dans le dossier values)

values/attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomTextView">
        <attr name="font" format="string"/>
    </declare-styleable>
</resources>

Puis créer notre nouvelle TextView, capable de récupérer l’attribut font, afin de modifier sa typeface :

CustomTextView.java

public class CustomTextView extends TextView {

    public CustomTextView(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.CustomTextView);
        String fontName = styledAttrs.getString(R.styleable.CustomTextView_font);
        styledAttrs.recycle();

        setTypeFace(fontName);
    }

    public void setTypeFace(String fontName) {
        if(fontName != null){
            try {
                Typeface typeface = Typeface.createFromAsset(getContext().getAssets(), "fonts/" + fontName);
                setTypeface(typeface);
            } catch (Exception e) {
                Log.e("FONT", fontName + " not found", e);
            }
        }
    }

}

L’activité se libère de la gestion des polices de caractère

MainActivity.java

public class MainActivity extends AppCompatActivity {

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

}

Son utilisation depuis le layout XML se fait simplement (penser à précéder CustomTextView par votre nom de package)

layout/activity_main.xml

<LinearLayout 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"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <TextView
        android:id="@+id/text1"
        android:layout_margin="10dp"
        android:textSize="25sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Police normal" />

    <com.tutosandroidfrance.customfont.CustomTextView
        android:id="@+id/text2"
        android:layout_margin="10dp"
        android:textSize="25sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Police personnalisée"
        app:font="Roboto-Light.ttf"/>

    <com.tutosandroidfrance.customfont.CustomTextView
        android:id="@+id/text3"
        android:layout_margin="10dp"
        android:textSize="25sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Police personnalisée"
        app:font="Roboto-Black.ttf"/>

</LinearLayout>

device-2015-06-30-170718

Amélioration

Le chargement d’une font ainsi que son stockage sont assez couteux, en terme de performance ou de mérmoire. Une optimisation possible est de stocker les fonts dans un cache, ici nommés LruCache :

public class CustomTextView extends TextView {

    //créé un cache de Typeface, pouvant contenir 12 fonts
    private static LruCache<String, Typeface> TYPEFACE_CACHE = new LruCache<String, Typeface>(12);

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

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

        //accède aux attributs ajoutés à cette CustomTextView
        TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView);

        //récupère l'attribut "font"
        String fontName = styledAttrs.getString(R.styleable.CustomTextView_font);

        //permet au garbage collector de récupérer l'espace utilisé par ce TypedArray
        styledAttrs.recycle();

        //puis modifie la font de cet élément
        setTypeFace(fontName);
    }

    public void setTypeFace(String fontName) {
        if(fontName != null){
            try {
                //on regarde dans le cache si cette police est présente
                Typeface typeface = TYPEFACE_CACHE.get(fontName);

                //si non, on la charge à partir des assets
                if (typeface == null) {
                    typeface = Typeface.createFromAsset(getContext().getAssets(),"fonts/" + fontName);

                    //puis on la sauvegarde dans notre cache
                    TYPEFACE_CACHE.put(fontName, typeface);
                }

                //puis on l'utilise sur notre TextView
                setTypeface(typeface);
            } catch (Exception e) {
                Log.e("FONT", fontName + " not found", e);
            }
        }
    }

}

Les sources de ce tutoriel sont disponibles sur github :

version activité

version custom view

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *