Utiliser une police personnalisée dans Android TextView en utilisant xml

J’ai ajouté un fichier de police personnalisé à mon dossier assets / fonts. Comment l’utiliser à partir de mon XML?

Je peux l’utiliser du code comme suit:

TextView text = (TextView) findViewById(R.id.textview03); Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/Molot.otf"); text.setTypeface(tf); 

Je ne peux pas le faire à partir de XML en utilisant un atsortingbut android:typeface="/fonts/Molot.otf" ?

Réponse courte: Non, Android ne prend pas en charge l’application de fonts personnalisées aux widgets de texte via XML.

Cependant, il existe une solution de rechange qui n’est pas très difficile à mettre en œuvre.

Premier

Vous devrez définir votre propre style. Dans votre dossier / res / values, ouvrez / créez le fichier attrs.xml et ajoutez un object déclar-styleable comme suit:

       

Seconde

En supposant que vous souhaitiez utiliser ce widget souvent, vous devriez configurer un cache simple pour les objects de Typeface chargés, car leur chargement à partir de la mémoire à la volée peut prendre du temps. Quelque chose comme:

 public class FontManager { private static FontManager instance; private AssetManager mgr; private Map fonts; private FontManager(AssetManager _mgr) { mgr = _mgr; fonts = new HashMap(); } public static void init(AssetManager mgr) { instance = new FontManager(mgr); } public static FontManager getInstance() { if (instance == null) { // App.getContext() is just one way to get a Context here // getContext() is just a method in an Application subclass // that returns the application context AssetManager assetManager = App.getContext().getAssets(); init(assetManager); } return instance; } public Typeface getFont(Ssortingng asset) { if (fonts.containsKey(asset)) return fonts.get(asset); Typeface font = null; try { font = Typeface.createFromAsset(mgr, asset); fonts.put(asset, font); } catch (Exception e) { } if (font == null) { try { Ssortingng fixedAsset = fixAssetFilename(asset); font = Typeface.createFromAsset(mgr, fixedAsset); fonts.put(asset, font); fonts.put(fixedAsset, font); } catch (Exception e) { } } return font; } private Ssortingng fixAssetFilename(Ssortingng asset) { // Empty font filename? // Just return it. We can't help. if (TextUtils.isEmpty(asset)) return asset; // Make sure that the font ends in '.ttf' or '.ttc' if ((!asset.endsWith(".ttf")) && (!asset.endsWith(".ttc"))) asset = Ssortingng.format("%s.ttf", asset); return asset; } } 

Celui-ci vous permettra d’utiliser les extensions de fichier .ttc, mais il n’a pas été testé.

Troisième

Créez une nouvelle classe qui sous-classe TextView . Cet exemple particulier prend en compte la police XML définie ( bold , italic , etc.) et l’applique à la police (en supposant que vous utilisez un fichier .ttc).

 /** * TextView subclass which allows the user to define a truetype font file to use as the view's typeface. */ public class FontText extends TextView { public FontText(Context context) { this(context, null); } public FontText(Context context, AtsortingbuteSet attrs) { this(context, attrs, 0); } public FontText(Context context, AtsortingbuteSet attrs, int defStyle) { super(context, attrs, defStyle); if (isInEditMode()) return; TypedArray ta = context.obtainStyledAtsortingbutes(attrs, R.styleable.FontText); if (ta != null) { Ssortingng fontAsset = ta.getSsortingng(R.styleable.FontText_typefaceAsset); if (!TextUtils.isEmpty(fontAsset)) { Typeface tf = FontManager.getInstance().getFont(fontAsset); int style = Typeface.NORMAL; float size = getTextSize(); if (getTypeface() != null) style = getTypeface().getStyle(); if (tf != null) setTypeface(tf, style); else Log.d("FontText", Ssortingng.format("Could not create a font from asset: %s", fontAsset)); } } } } 

finalement

Remplacez les instances de TextView dans votre XML par le nom de classe qualifié complet. Déclarez votre espace de noms personnalisé comme vous le feriez pour l’espace de noms Android. Notez que “typefaceAsset” doit pointer sur un fichier .ttf ou .ttc contenu dans votre répertoire / assets.

    

Voici un exemple de code qui fait cela. J’ai la police définie dans une variable finale statique et le fichier de police se trouve dans le répertoire des actifs.

 public class TextViewWithFont extends TextView { public TextViewWithFont(Context context, AtsortingbuteSet attrs) { super(context, attrs); this.setTypeface(MainActivity.typeface); } public TextViewWithFont(Context context, AtsortingbuteSet attrs, int defStyle) { super(context, attrs, defStyle); this.setTypeface(MainActivity.typeface); } public TextViewWithFont(Context context) { super(context); this.setTypeface(MainActivity.typeface); } } 

Créez votre TextView personnalisé appartient à la police que vous souhaitez utiliser. Dans cette classe, j’utilise un champ statique mTypeface pour mettre en cache le caractère (pour de meilleures performances)

 public class HeliVnTextView extends TextView { /* * Caches typefaces based on their file path and name, so that they don't have to be created every time when they are referenced. */ private static Typeface mTypeface; public HeliVnTextView(final Context context) { this(context, null); } public HeliVnTextView(final Context context, final AtsortingbuteSet attrs) { this(context, attrs, 0); } public HeliVnTextView(final Context context, final AtsortingbuteSet attrs, final int defStyle) { super(context, attrs, defStyle); if (mTypeface == null) { mTypeface = Typeface.createFromAsset(context.getAssets(), "HelveticaiDesignVnLt.ttf"); } setTypeface(mTypeface); } } 

Dans un fichier xml:

  

En classe java:

 HeliVnTextView title = new HeliVnTextView(getActivity()); title.setText(issue.getName()); 

Activity implémente LayoutInflater.Factory2 qui fournit des rappels sur chaque vue créée. Il est possible de styliser TextView avec l’atsortingbut fontFamily personnalisé, de charger les fonts à la demande et d’appeler automatiquement setTypeface sur les vues de texte instanciées.

Malheureusement, en raison de la relation architecturale entre les instances d’Inflater et les activités et Windows, l’approche la plus simple consiste à mettre en cache les fonts chargées au niveau de l’application.

L’échantillon de base de code est ici:

https://github.com/leok7v/android-textview-custom-fonts

      

résulte en

entrer la description de l'image ici

Ce n’est pas une bonne idée d’utiliser des fonts personnalisées au format XML car vous devez le faire par programme pour éviter les memory leaks!

MISE À JOUR: https://github.com/chrisjenx/Calligraphy semble être une solution supérieure à cela.


Vous pouvez peut-être utiliser la reflection pour injecter / pirater votre police dans la liste statique des fonts disponibles lors de la création de votre application? Je suis intéressé par les commentaires des autres si c’est une très, très mauvaise idée ou si c’est une excellente solution – il semble que ce sera l’un de ces extrêmes …

J’ai pu injecter ma police de caractères personnalisée dans la liste des fonts système avec mon propre nom de famille, puis spécifier le nom de famille de fonts personnalisé (“pinceau-script”) comme valeur d’ android: FontFamily sur un TextView standard fonctionnant sur mon LG G4 sous Android 6.0.

 public class MyApplication extends android.app.Application { @Override public void onCreate() { super.onCreate(); Typeface font = Typeface.createFromAsset(this.getResources().getAssets(),"fonts/brush-script.ttf"); injectTypeface("brush-script", font); } private boolean injectTypeface(Ssortingng fontFamily, Typeface typeface) { try { Field field = Typeface.class.getDeclaredField("sSystemFontMap"); field.setAccessible(true); Object fieldValue = field.get(null); Map map = (Map) fieldValue; map.put(fontFamily, typeface); return true; } catch (Exception e) { Log.e("Font-Injection", "Failed to inject typeface.", e); } return false; } } 

Dans ma mise en page

  

Je sais que c’est une vieille question, mais j’ai une solution beaucoup plus facile.

D’abord, déclarez votre TextView en XML comme d’habitude. Mettez votre police (TTF ou TTC) dans le dossier de ressources

app \ src \ main \ assets \

Ensuite, définissez simplement la police pour votre vue texte dans votre méthode onCreate.

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_name); TextView textView = findViewById(R.id.my_textView); Typeface typeface = Typeface.createFromAsset(getAssets(), "fontName.ttf"); textView.setTypeface(typeface); } 

Terminé.

Créez un dossier de fonts dans les actifs et ajoutez-y toutes les fonts requirejses.

 public class CustomTextView extends TextView { private static final Ssortingng TAG = "TextView"; public CustomTextView(Context context) { super(context); } public CustomTextView(Context context, AtsortingbuteSet attrs) { super(context, attrs); setCustomFont(context, attrs); } public CustomTextView(Context context, AtsortingbuteSet attrs, int defStyle) { super(context, attrs, defStyle); setCustomFont(context, attrs); } private void setCustomFont(Context ctx, AtsortingbuteSet attrs) { TypedArray a = ctx.obtainStyledAtsortingbutes(attrs, R.styleable.CustomTextView); Ssortingng customFont = a.getSsortingng(R.styleable.CustomTextView_customFont); setCustomFont(ctx, customFont); a.recycle(); } public boolean setCustomFont(Context ctx, Ssortingng fontName) { Typeface typeface = null; try { if(fontName == null){ fontName = Constants.DEFAULT_FONT_NAME; } typeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/" + fontName); } catch (Exception e) { Log.e(TAG, "Unable to load typeface: "+e.getMessage()); return false; } setTypeface(typeface); return true; } } 

et append un déclarable dans attrs.xml

    

puis ajoutez votre customFont comme

 app:customFont="arial.ttf" 

au lieu de xmlns: custom = “schemas.android.com/tools”; vous devez utiliser: xmlns: custom = “schemas.android.com/apk/res-auto”; afin d’utiliser des atsortingbuts stylables. J’ai fait ce changement et ça marche maintenant.