¿Puedo cambiar la fuente desde el xml? Sí, pero…
Una forma alternativa y muy recomendable para hacer más fácil el uso de fuentes es crear un TextView personalizado al que podamos agregarle la fuente que queremos usar desde el archivo xml, ahorrándonos tener que agregar líneas extra en el código java. Para realiza nuestro TextView personalizado tendremos que definir un atributo «fuente» que podamos usar en el layout.xml, cuyo valor será el de la ruta a la fuente que queremos usar en dicho caso, y tendremos que modificar los constructores de la clase TextView para que haga uso de ese atributo. Esto permitirá utilizar cualquier fuente que carguemos con una misma clase TextView.Paso a paso
Realizar un TextView personalizado consta de los siguientes pasos:- Definir un recurso
declare-styleable
que contendrá el atributo «fuente» para indicar la ruta a la fuente en el xml - Hacer uso del atributo «fuente» en el xml
- Crear una clase que herede de TextView que utilice la fuente que especifiquemos en el xml
1. Definir un recurso declare-styleable
Crearemos el archivo attr.xml en la carpeta values (app/src/main/res/values) donde añadiremos un elemento declare-styleable
con el atributo name="Extra"
y un elemento <attr>
llamado «fuente» y que sea de formato String.
1 2 3 4 5 6 |
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="Extra"> <attr name="fuente" format="string"/> </declare-styleable> </resources> |
declare-styleable
como al elemento <attr>
, podemos ponerle el nombre que queramos, pero debemos tenerlo presente para el siguiente paso.
2. Crear una clase que herede de TextView
Llamaremos a esta clase «TextViewPersonalizado«. Debemos sobrescribir todos los constructores de la clase y fijaros en los que reciben un AttributeSet (el conjunto de atributos que recibe del xml): TextViewPersonalizado.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public class TextViewPersonalizado extends TextView { public TextViewPersonalizado(Context context) { super(context); } public TextViewPersonalizado(Context context, AttributeSet attrs) { super(context, attrs); setTypeface(context, attrs); } public TextViewPersonalizado(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setTypeface(context, attrs); } public void setTypeface(Context context, AttributeSet attrs){ TypedArray styledAttributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.Extra, 0, 0); String fuente = fuente = styledAttributes.getString(R.styleable.Extra_fuente); styledAttributes.recycle(); if (fuente != null) setTypeface(TypefacesUtils.get(context, fuente)); } } |
context
, por lo que no nos sirve, aunque debemos sobrescribirlo igualmente. El segundo y el tercero sí reciben un AttributeSet. Para no repetir código, hemos creado el método setTypeface()
, que obtiene el atributo «fuente» y cambia la tipografía. Lo llamaremos solamente desde estos dos últimos constructores.
¿Cómo funciona? En el atributo «fuente» habremos escrito (paso 3) la ruta a la tipografía que queremos usar a partir de la carpeta app/src/main/assets. Para obtener esta ruta se utiliza el método obtainStyledAttributes()
cuyos parámetros son:
- El conjunto de atributos de la vista
- El conjunto de atributos que queremos recuperar
- El atributo que hay en el tema actual que referencia al recurso donde se indican los valores por defecto para ese AttributeSet
- El archivo de recursos que contiene los valores por defecto para este AttributeSet
R.styleable.Extra
, que será el id que se habrá asignado al declare-styleable
que definimos en el primer apartado.
A continuación obtenemos el valor del atributo «fuente» con el método TypedArray.getString()
, igual que si fuera un Bundle, es decir, pasándole la clave del valor que queremos recuperar. Este identificador se habrá guardado en R como R.styleable.Extra_fuente
, ya que el nombre que le asignamos al atributo era «fuente». Y dado que le indicamos que el atributo tenía un formato de String, lo guardamos en una variable de tipo String. Luego, llamamos al método TyperArray.recycle()
, que permitirá a la aplicación seguir utilizando ese TypedArray.
El método getString()
devolverá nulo si no existe el valor indicado, por lo que, antes de seguir, debemos comprobar si es nulo o no. Si no lo es, el valor será el valor que indicamos en el xml, por lo que ahora podemos utilizarlo para obtener la fuente, ya sea con la clase TypefacesUtils que definimos en el tutorial anterior o llamando simplemente a setTypeface(Typefaces.createFromAssets(context, rutaFuente)
.
3. Hacer uso del atributo
Después de esto, vamos al layout donde queremos utilizar nuestro TextViewPersonalizado y lo declaramos de la siguiente manera:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:codictados="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp"> <codictados.tutoriales.TextViewPersonalizado android:id="@+id/normal" android:layout_width="match_parent" android:layout_height="wrap_content" android:textStyle="normal" codictados:fuente="fonts/DejaVuSans.ttf" android:text="DejaVuSans"/> </LinearLayout> |
android
«, ya que ese está en uso. Para crearlo solo tenemos que escribir algún atributo utilizando ese namespace y se nos ofrecerá la opción de importarlo con Alt + Intro. Es decir, que si escribimos «codictados:fuente
«, se nos ofrecerá la opción de crear el namespace. El valor tiene que ser el primero de la lista: «http://schemas.android.com/apk/res-auto».
Una vez hecho esto, podemos indicar en este atributo la ruta a cualquier fuente que tengamos en app/src/main/assets/fonts comenzando por «fonts/».