Des polices personnalisées et des mises en page XML (Android)

j'essaie de définir une mise en page GUI en utilisant des fichiers XML dans Android. Pour autant que je sache, il n'y a aucun moyen de spécifier que vos widgets doivent utiliser une police personnalisée (par exemple celle que vous avez placée dans assets/font/) dans les fichiers XML et vous ne pouvez utiliser que les polices installées par le système.

je sais que, dans le code Java, je pourrais changer la police de chaque widget manuellement en utilisant des identifiants uniques. Sinon, je pourrais parcourir toutes les widgets en Java pour faire ce changement, mais ce serait probablement être très lent.

quelles autres options ai-je? Est-il de meilleures façons de faire les widgets qui ont un look custom? Je ne veux pas particulièrement avoir à changer manuellement la police pour chaque nouveau widget que j'ajoute.

170
demandé sur DrDefrost 2010-03-04 04:13:15

17 réponses

vous pouvez étendre TextView pour définir des polices personnalisées comme j'ai appris ici .

TextViewPlus.java:

package com.example;

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

public class TextViewPlus extends TextView {
    private static final String TAG = "TextView";

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

    public TextViewPlus(Context context, AttributeSet attrs) {
        super(context, attrs);
        setCustomFont(context, attrs);
    }

    public TextViewPlus(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setCustomFont(context, attrs);
    }

    private void setCustomFont(Context ctx, AttributeSet attrs) {
        TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.TextViewPlus);
        String customFont = a.getString(R.styleable.TextViewPlus_customFont);
        setCustomFont(ctx, customFont);
        a.recycle();
    }

    public boolean setCustomFont(Context ctx, String asset) {
        Typeface tf = null;
        try {
        tf = Typeface.createFromAsset(ctx.getAssets(), asset);  
        } catch (Exception e) {
            Log.e(TAG, "Could not get typeface: "+e.getMessage());
            return false;
        }

        setTypeface(tf);  
        return true;
    }

}

attrs.xml: (dans res/valeurs)

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

principal.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:foo="http://schemas.android.com/apk/res/com.example"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <com.example.TextViewPlus
        android:id="@+id/textViewPlus1"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:text="@string/showingOffTheNewTypeface"
        foo:customFont="saxmono.ttf">
    </com.example.TextViewPlus>
</LinearLayout>

vous mettriez" saxmono.ttf" dans le dossier assets .

Mise à jour 01/08/13

cette méthode pose de graves problèmes de mémoire. Voir le commentaire de chedabob ci-dessous.

218
répondu peter 2017-05-23 11:54:41

je suis en retard de 3 ans pour le parti :( cependant cela pourrait être utile pour quelqu'un qui pourrait tomber sur ce poste.

j'ai écrit une bibliothèque qui cache les polices de caractères et vous permet également de spécifier des polices de caractères personnalisées directement à partir de XML. Vous pouvez trouver la bibliothèque ici .

voici à quoi ressemblerait votre mise en page XML lorsque vous l'utiliserez.

<com.mobsandgeeks.ui.TypefaceTextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world"
    geekui:customTypeface="fonts/custom_font.ttf" />
35
répondu Ragunath Jawahar 2013-05-09 11:58:20

c'est peut-être un peu tard, mais vous devez créer une classe singleton qui renvoie le caractère personnalisé pour éviter les fuites de mémoire.

classe de police de caractères:

public class OpenSans {

private static OpenSans instance;
private static Typeface typeface;

public static OpenSans getInstance(Context context) {
    synchronized (OpenSans.class) {
        if (instance == null) {
            instance = new OpenSans();
            typeface = Typeface.createFromAsset(context.getResources().getAssets(), "open_sans.ttf");
        }
        return instance;
    }
}

public Typeface getTypeFace() {
    return typeface;
}
}

Custom TextView:

public class NativelyCustomTextView extends TextView {

    public NativelyCustomTextView(Context context) {
        super(context);
        setTypeface(OpenSans.getInstance(context).getTypeFace());
    }

    public NativelyCustomTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setTypeface(OpenSans.getInstance(context).getTypeFace());
    }

    public NativelyCustomTextView(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
        setTypeface(OpenSans.getInstance(context).getTypeFace());
    }

}

par xml:

<com.yourpackage.views.NativelyCustomTextView
            android:id="@+id/natively_text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_margin="20dp"
            android:text="@string/natively"
            android:textSize="30sp" /> 

Programme:

TextView programmaticallyTextView = (TextView) 
       findViewById(R.id.programmatically_text_view);

programmaticallyTextView.setTypeface(OpenSans.getInstance(this)
                .getTypeFace());
18
répondu Leonardo Cardoso 2015-01-03 07:30:58

question ancienne, mais je suis sûr que j'aimerais lire cette réponse ici avant de commencer ma propre recherche pour une bonne solution. Calligraphie étend l'attribut android:fontFamily pour ajouter la prise en charge des polices personnalisées dans votre dossier d'actifs, comme suit:

<TextView 
  android:text="@string/hello_world"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:fontFamily="fonts/Roboto-Bold.ttf"/>

La seule chose que vous avez à faire pour l'activer, il est attachant au Contexte de l'Activité que vous utilisez:

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

vous pouvez également spécifier votre propre attribut personnalisé à remplacer android:fontFamily

il fonctionne également dans des thèmes, y compris L'Appthème.

13
répondu thoutbeckers 2014-05-01 16:08:40

si vous n'avez qu'une police que vous aimeriez ajouter, et que vous voulez moins de code à écrire, vous pouvez créer un TextView dédié à votre police spécifique. Voir le code ci-dessous.

package com.yourpackage;
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;

public class FontTextView extends TextView {
    public static Typeface FONT_NAME;


    public FontTextView(Context context) {
        super(context);
        if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "fonts/FontName.otf");
        this.setTypeface(FONT_NAME);
    }
    public FontTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "fonts/FontName.otf");
        this.setTypeface(FONT_NAME);
    }
    public FontTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "fonts/FontName.otf");
        this.setTypeface(FONT_NAME);
    }
}

.xml, vous pouvez maintenant ajouter votre textView comme ceci:

<com.yourpackage.FontTextView
    android:id="@+id/tvTimer"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="" />
7
répondu Tore Rudberg 2012-05-02 13:30:18

Utilisant DataBinding :

@BindingAdapter({"bind:font"})
public static void setFont(TextView textView, String fontName){
 textView.setTypeface(Typeface.createFromAsset(textView.getContext().getAssets(), "fonts/" + fontName));
}

en XML:

<TextView
app:font="@{`Source-Sans-Pro-Regular.ttf`}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

le fichier de police doit être dans assets/fonts/

7
répondu Abdellah 2015-09-03 16:51:16

la meilleure façon de le faire à partir de Android O preview release est de cette façon

1.) Faites un clic droit sur le dossier res et passez à nouveau > Android resource directory . Le Nouveau

La fenêtre du répertoire de ressources apparaît.

2.)Dans la liste des types de ressources, sélectionnez font , puis cliquez sur OK.

3.) Ajoutez vos fichiers de police dans le dossier de police .La structure de dossier ci-dessous génère R. font.dancing_script, R. font.la_la, et R. font.ba_ba.

4.) double-cliquez sur un fichier de police pour prévisualiser les polices du fichier dans l'éditeur.

ensuite, nous devons créer une famille de polices de caractères

1.) Cliquez avec le bouton droit de la souris sur le dossier de police et passez à nouveau > fichier de ressources de police . La nouvelle fenêtre du fichier ressource apparaît.

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

3.) Inclure chaque attribut de fichier de police, de style et de poids dans l'élément de l'étiquette de police. Le XML suivant illustre l'ajout d'attributs liés à la police dans la ressource de police XML:

<?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/hey_regular" />
    <font
    android:fontStyle="italic"
    android:fontWeight="400"
    android:font="@font/hey_bababa" />
</font-family>

ajouter des polices à un TextView:

   <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    **android:fontFamily="@font/ba_ba"**/>

d'après la documentation

Travailler Avec Les Polices

toutes les étapes sont correctes.

6
répondu jeevan s 2017-03-28 05:32:01

Étendre TextView et lui donner un attribut personnalisé ou tout simplement utiliser android:attribut de balise pour passer dans une Chaîne de quelle police que vous souhaitez utiliser. Vous devrez choisir une convention et vous y tenir comme je mettrai toutes mes polices dans le res/assets/fonts/ folder pour que votre classe TextView sache où les trouver. Ensuite, dans votre constructeur, vous définissez la police manuellement après le super call.

5
répondu schwiz 2011-02-24 19:38:25

la seule façon d'utiliser des polices personnalisées est de passer par le code source.

rappelez-vous juste que Android fonctionne sur des appareils avec des ressources très limitées et les polices peuvent nécessiter une bonne quantité de RAM. Les polices droïdes intégrées sont spécialement faites et, si vous notez, ont de nombreux caractères et décorations manquants.

4
répondu Tareq Sha 2010-03-06 00:04:48

je pourrais avoir une réponse simple à la question sans étendre le TextView et implémenter un code long.

Code:

 TextView tv = (TextView) findViewById(R.id.textview1);
    tv.setTypeface(Typeface.createFromAsset(getAssets(), "font.ttf"));

placez le fichier de police personnalisé dans le dossier assets comme d'habitude et essayez ceci. Il fonctionne pour moi. Je ne comprends pas pourquoi peter a donné un tel code énorme pour cette chose simple ou il a donné sa réponse dans l'ancienne version.

2
répondu San 2013-12-13 09:18:00

peut aussi être défini dans le xml sans créer de classes personnalisées

de style.xml

<style name="ionicons" parent="android:TextAppearance">
    <!-- Custom Attr-->
    <item name="fontPath">fonts/ionicons.ttf</item>
</style>

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="@style/ionicons"
        android:text=""/>
</LinearLayout>

une note rapide, parce que j'ai toujours oublié où mettre les polices, c'est que la police doit être à l'intérieur de assets et ce dossier se trouve dans le même niveau que res et src , dans mon cas son assets/fonts/ionicons.ttf

mise à Jour , a Ajouté la racine de la mise en page parce que cette méthode doit xmlns:app="http://schemas.android.com/apk/res-auto" travailler

mise à jour 2 J'ai oublié une bibliothèque que j'ai installée avant appelé Calligraphie

2
répondu norman784 2015-11-05 18:58:45

la réponse de Peter est la meilleure, mais elle peut être améliorée en utilisant les styles.xml D'Android pour personnaliser vos polices de caractères pour tous les textviews dans votre application.

mon code est ici

1
répondu Jelle 2017-05-23 12:18:18

il y a deux façons de personnaliser les polices:

!!! mes polices personnalisées dans les actifs/fonts/iran_sans.ttf

Voie 1 : Refrection La Police De Caractères.la classe ||| meilleure façon

appelez FontsOverride.setDefaultFont () dans class extends Application, ce code va faire changer toutes les polices du logiciel, même les polices Toasts

AppController.java

public class AppController extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        //Initial Font
        FontsOverride.setDefaultFont(getApplicationContext(), "MONOSPACE", "fonts/iran_sans.ttf");

    }
}

FontsOverride.java

public class FontsOverride {

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

    private 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();
        }
    }
}

voie 2: utiliser setTypeface

pour une vue spéciale, il suffit d'appeler setTypeface() pour changer de police.

TextView.java

public class CTextView extends TextView {

    public CTextView(Context context) {
        super(context);
        init(context,null);
    }

    public CTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context,attrs);
    }

    public CTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context,attrs);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public CTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context,attrs);
    }

    public void init(Context context, @Nullable AttributeSet attrs) {

        if (isInEditMode())
            return;

        // use setTypeface for change font this view
        setTypeface(FontUtils.getTypeface("fonts/iran_sans.ttf"));

    }
}

FontUtils.java

public class FontUtils {

    private static Hashtable<String, Typeface> fontCache = new Hashtable<>();

    public static Typeface getTypeface(String fontName) {
        Typeface tf = fontCache.get(fontName);
        if (tf == null) {
            try {
                tf = Typeface.createFromAsset(AppController.getInstance().getApplicationContext().getAssets(), fontName);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
            fontCache.put(fontName, tf);
        }
        return tf;
    }

}
1
répondu Rasoul Miri 2017-08-30 12:32:27

voici un tutoriel qui vous montre comment configurer une police personnalisée comme @peter décrit: http://responsiveandroid.com/2012/03/15/custom-fonts-in-android-widgets.html

il a également la considération pour les fuites de mémoire potentielles ala http://code.google.com/p/android/issues/detail?id=9904 . Aussi dans le tutoriel est un exemple pour définir une police personnalisée sur un bouton.

0
répondu browep 2014-12-12 21:56:59

vous pouvez facilement personnaliser la classe textview: -

donc ce que vous devez faire en premier, faire Custom textview classe qui s'étend avec AppCompatTextView .

public class CustomTextView extends AppCompatTextView {
    private int mFont = FontUtils.FONTS_NORMAL;
    boolean fontApplied;

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

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

    public CustomTextView(Context context) {
        super(context);
        init(null, context);
    }

    protected void init(AttributeSet attrs, Context cxt) {
        if (!fontApplied) {
            if (attrs != null) {
                mFont = attrs.getAttributeIntValue(
                        "http://schemas.android.com/apk/res-auto", "Lato-Regular.ttf",
                        -1);
            }
            Typeface typeface = getTypeface();
            int typefaceStyle = Typeface.NORMAL;
            if (typeface != null) {
                typefaceStyle = typeface.getStyle();
            }
            if (mFont > FontUtils.FONTS) {
                typefaceStyle = mFont;
            }
            FontUtils.applyFont(this, typefaceStyle);
            fontApplied = true;
        }
    }
}

maintenant, chaque fois que L'appel de vue de texte personnalisé et nous obtiendrons la valeur int de l'attribut int fontValue = attrs.getAttributeIntValue("http://schemas.android.com/apk/res-auto","Lato-Regular.ttf",-1) .

ou

nous pouvons aussi obtenir getTypeface() à partir de la vue que nous avons définie dans notre xml ( android:textStyle="bold|normal|italic" ). Donc, faites ce que vous voulez faire.

Maintenant, nous faisons FontUtils pour tout .TTF font dans notre vue.

public class FontUtils {

    public static final int FONTS = 1;
    public static final int FONTS_NORMAL = 2;
    public static final int FONTS_BOLD = 3;
    public static final int FONTS_BOLD1 = 4;

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

    static Typeface getFonts(Context context, String name) {
        Typeface typeface = TYPEFACE.get(name);
        if (typeface == null) {
            typeface = Typeface.createFromAsset(context.getAssets(), name);
            TYPEFACE.put(name, typeface);
        }
        return typeface;
    }

    public static void applyFont(TextView tv, int typefaceStyle) {

        Context cxt = tv.getContext();
        Typeface typeface;

        if(typefaceStyle == Typeface.BOLD_ITALIC) {
            typeface = FontUtils.getFonts(cxt, "FaktPro-Normal.ttf");
        }else if (typefaceStyle == Typeface.BOLD || typefaceStyle == SD_FONTS_BOLD|| typefaceStyle == FONTS_BOLD1) {
            typeface = FontUtils.getFonts(cxt, "FaktPro-SemiBold.ttf");
        } else if (typefaceStyle == Typeface.ITALIC) {
            typeface = FontUtils.getFonts(cxt, "FaktPro-Thin.ttf");
        } else {
            typeface = FontUtils.getFonts(cxt, "FaktPro-Normal.ttf");
        }
        if (typeface != null) {
            tv.setTypeface(typeface);
        }
    }
}
0
répondu duggu 2018-02-06 11:34:08

Fontinator est un Android-bibliothèque le rendre facile, d'utiliser des polices personnalisées. https://github.com/svendvd/Fontinator

-1
répondu Sven Nähler 2014-11-30 10:41:40

vous ne pouvez pas étendre TextView pour créer un widget ou utiliser un dans une mise en page de widgets: http://developer.android.com/guide/topics/appwidgets/index.html

-5
répondu Carl Whalley 2011-03-16 18:36:49