Fuentes personalizadas y diseños de XML (Android)

Estoy tratando de definir un diseño de GUI usando archivos XML en Android. Por lo que puedo averiguar, no hay forma de especificar que tus widgets deberían usar una fuente personalizada (por ejemplo, una que hayas colocado en assets / font /) en archivos XML y solo puedes usar las fonts instaladas en el sistema.

Sé que, en el código de Java, podría cambiar la fuente de cada artilugio de forma manual con ID únicos. Alternativamente, podría iterar sobre todos los widgets en Java para hacer este cambio, pero esto probablemente sería muy lento.

¿Qué otras opciones tengo? ¿Hay alguna forma mejor de hacer widgets que tengan un aspecto personalizado? En particular, no quiero tener que cambiar manualmente la fuente para cada nuevo widget que agregue.

Puede ampliar TextView para establecer fonts personalizadas como aprendí aquí .

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: (en res / valores)

       

main.xml:

      

Debería poner “saxmono.ttf” en la carpeta de activos .

ACTUALIZACIÓN 01/08/13

Hay preocupaciones serias de memoria con este método. Ver el comentario de chedabob a continuación.

Tengo 3 años de retraso para la fiesta 🙁 Sin embargo, esto podría ser útil para alguien que podría tropezar con esta publicación.

Escribí una biblioteca que almacena en caché los Tipos de letra y también le permití especificar tipos de letra personalizados directamente desde XML. Puedes encontrar la biblioteca aquí .

Así es como se vería su diseño XML cuando lo usa.

  

Esto podría ser un poco tarde, pero necesita crear una clase singleton que devuelva el tipo de letra personalizado para evitar pérdidas de memoria.

Clase TypeFace:

 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; } } 

TextView personalizado:

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

Por xml:

  

Progtwigdo:

 TextView programmaticallyTextView = (TextView) findViewById(R.id.programmatically_text_view); programmaticallyTextView.setTypeface(OpenSans.getInstance(this) .getTypeFace()); 

Una vieja pregunta, pero seguramente me gustaría leer esta respuesta aquí antes de comenzar mi propia búsqueda de una buena solución. La caligrafía amplía el atributo android:fontFamily para agregar compatibilidad con fonts personalizadas en la carpeta de sus activos, así:

  

Lo único que tienes que hacer para activarlo es adjuntarlo al contexto de la actividad que estás utilizando:

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

También puede especificar su propio atributo personalizado para reemplazar a android:fontFamily

También funciona en temas, incluido AppTheme.

Si solo tiene un tipo de letra que desea agregar y desea menos código para escribir, puede crear un TextView dedicado para su fuente específica. Vea el código a continuación.

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

En main.xml, ahora puede agregar su textView de esta manera:

  

Usando DataBinding :

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

En XML:

  

el archivo de fuente debe estar en assets/fonts/

La mejor forma de hacerlo desde Android O el lanzamiento de vista previa es de esta manera
1.) Haga clic con el botón derecho en la carpeta res y vaya a Nuevo> Directorio de recursos de Android . El nuevo
La ventana del Directorio de Recursos aparece.
2.) En la lista Tipo de recurso, seleccione fuente y luego haga clic en Aceptar.
3.) Agregue sus archivos de fonts en la carpeta de fonts . La estructura de carpetas a continuación genera R.font.dancing_script, R.font.la_la y R.font.ba_ba.
4.) Haga doble clic en un archivo de fuente para previsualizar las fonts del archivo en el editor.

A continuación, debemos crear una familia de fonts

1.) Haga clic con el botón derecho en la carpeta de fonts y vaya a Nuevo> Archivo de recursos de fonts . Aparece la ventana Nuevo archivo de recursos.
2.) Ingrese el nombre del archivo y luego haga clic en Aceptar . El nuevo XML de recurso de fuente se abre en el editor.
3.) Adjunte cada archivo de fuente, estilo y atributo de peso en el elemento de etiqueta de fuente. El siguiente XML ilustra la adición de atributos relacionados con la fuente en el XML de recursos de fonts:

      

Agregar fonts a un TextView:

   

A partir de la documentación

Trabajando con fonts

todos los pasos son correctos.

Extienda TextView y dele un atributo personalizado o simplemente use el atributo android: tag para pasar una Cadena de la fuente que desea usar. Tendrá que elegir una convención y atenerse a ella, como pondré todas mis fonts en la carpeta res / assets / fonts / para que su clase TextView sepa dónde encontrarlas. Luego, en tu constructor, simplemente estableces la fuente manualmente después de la súper llamada.

La única forma de usar fonts personalizadas es a través del código fuente.

Solo recuerde que Android se ejecuta en dispositivos con recursos muy limitados y las fonts pueden requerir una buena cantidad de RAM. Las fonts Droid incorporadas están hechas especialmente y, si se nota, tienen muchos caracteres y decoraciones faltantes.

Es posible que tenga una respuesta simple para la pregunta sin extender el TextView e implementar un código largo.

Código:

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

Coloque el archivo de fuente personalizado en la carpeta de activos como de costumbre e intente esto. Esto funciona para mi. Simplemente no entiendo por qué Peter ha dado un código tan grande para esta simple cosa o ha dado su respuesta en una versión anterior.

También se puede definir en el xml sin crear clases personalizadas

style.xml

  

activity_main.xml

    

Una nota rápida, porque siempre olvidé dónde poner las fonts, es que la fuente debe estar dentro de los assets y esta carpeta reside en el mismo nivel que res y src , en mi caso es assets/fonts/ionicons.ttf

Se ha actualizado el diseño de raíz añadido porque este método necesita xmlns:app="http://schemas.android.com/apk/res-auto" para trabajar

Actualización 2 Olvidé una biblioteca que instalé antes llamada Caligrafía

Hay dos formas de personalizar fonts:

!!! mi fuente personalizada en assets / fonts / iran_sans.ttf

Modo 1: Refrection Typeface.class

mejor manera

llamada FontsOverride.setDefaultFont () en la clase extends Application, Este código hará que cambien todas las fonts de software, incluso las fonts de 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(); } } } 

Modo 2: use setTypeface

para una vista especial simplemente llame a setTypeface () para cambiar la fuente.

CTextView.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 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; } } 

La respuesta de Peter es la mejor, pero puede mejorarse utilizando styles.xml de Android para personalizar las fonts de todas las textviews en su aplicación.

Mi código está aquí

Aquí hay un tutorial que le muestra cómo configurar una fuente personalizada como @peter describió: http://responsiveandroid.com/2012/03/15/custom-fonts-in-android-widgets.html

también tiene en cuenta posibles memory leaks en http://code.google.com/p/android/issues/detail?id=9904 . También en el tutorial hay un ejemplo para configurar una fuente personalizada en un botón.

Puede hacer una clase de vista de texto fácilmente personalizada:

Entonces, qué debe hacer primero, haga Custom textview clase de vista de Custom textview que se amplíe con 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; } } } 

Ahora, cada vez que se visualice texto personalizado, obtendremos el valor int del atributo int fontValue = attrs.getAttributeIntValue("http://schemas.android.com/apk/res-auto","Lato-Regular.ttf",-1) .

O

También podemos obtener getTypeface () de la vista que configuramos en nuestro xml ( android:textStyle="bold|normal|italic" ). Haz lo que quieras hacer.

Ahora, hacemos FontUtils para configurar cualquier fuente .ttf en nuestra vista.

 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 TYPEFACE = new HashMap(); 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); } } } 

Fontinator es una biblioteca de Android que facilita el uso de fonts personalizadas. https://github.com/svendvd/Fontinator

No puede extender TextView para crear un widget o usar uno en un diseño de widgets: http://developer.android.com/guide/topics/appwidgets/index.html