Android: desea configurar fuentes personalizadas para toda la aplicación, no en tiempo de ejecución

100

¿Es posible configurar una fuente personalizada en cada control de la aplicación? ¿Y no necesariamente en tiempo de ejecución? (es decir, desde xml si es posible o solo una vez para toda la aplicación en el archivo JAVA)

Puedo configurar la fuente para un control de este código.

public static void setFont(TextView textView) {
    Typeface tf = Typeface.createFromAsset(textView.getContext()
            .getAssets(), "fonts/BPreplay.otf");

    textView.setTypeface(tf);

}

Y el problema con este código es que debería llamarse para cada control. Y quiero llamar a este o cualquier método similar una vez, o si es posible, establecer la propiedad en xml. ¿Es posible?

Prasham
fuente
6
Puede ser que pueda escribir un control personalizado extendiendo TextView y establecer la fuente en el constructor podría ser una opción. Entonces puede usar este control en toda la aplicación en lugar de su vista de texto. También para ahorrar memoria, puede evitar la carga de recursos utilizando un tipo de letra estático.
Varun
@Varun: bueno, esta idea puede ahorrarme tiempo, pero tengo que configurar todos los controles, y escribir un control personalizado para cada uno será una forma más larga que configurar un tiempo de ejecución de fuente, ¿qué piensas? (Sin embargo +1 para escribir control personalizado)
Prasham
Es posible que desee escribir solo un control personalizado que extienda el textView y la única modificación será la configuración del tipo de letra. Al usar el control cusotm en sus archivos de diseño, no tiene que hacerlo manualmente cada vez para cada vista de texto y aún puede estar seguro de que está usando la fuente que desea.
Varun
¿Qué hay de escribir una costumbre en VIEWlugar de escribir una custom text viewy una por custom button viewseparado? Mi requisito es para todos los controles, y la vista de texto fue solo un ejemplo. Lo siento, olvidé mencionarlo ... :-(
Prasham
1
Eche un vistazo a la pregunta de satckoverflow stackoverflow.com/questions/2711858/… que le ayuda.
Ashwini

Respuestas:

123

EDITAR : Ha pasado un tiempo y me gustaría agregar lo que creo que es la mejor manera de hacer esto, ¡y a través de XML nada menos!

Entonces, primero, querrá crear una nueva clase que anule cualquier Vista que desee personalizar. (por ejemplo, ¿quieres un botón con un tipo de letra personalizado? Ampliar Button). Hagamos un ejemplo:

public class CustomButton extends Button {
    private final static int ROBOTO = 0;
    private final static int ROBOTO_CONDENSED = 1;

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

    public CustomButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        parseAttributes(context, attrs); //I'll explain this method later
    }

    public CustomButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        parseAttributes(context, attrs);
    }
}

Ahora, si no tiene uno, agregue un documento XML debajo res/values/attrs.xmly agregue:

<resources>
    <!-- Define the values for the attribute -->
    <attr name="typeface" format="enum">
        <enum name="roboto" value="0"/>
        <enum name="robotoCondensed" value="1"/>
    </attr>

    <!-- Tell Android that the class "CustomButton" can be styled, 
         and which attributes it supports -->
    <declare-styleable name="CustomButton">
        <attr name="typeface"/>
    </declare-styleable>
</resources>

Bien, con eso fuera del camino, volvamos al parseAttributes()método de antes:

private void parseAttributes(Context context, AttributeSet attrs) {
    TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.CustomButton);

    //The value 0 is a default, but shouldn't ever be used since the attr is an enum
    int typeface = values.getInt(R.styleable.CustomButton_typeface, 0);

    switch(typeface) {
        case ROBOTO: default:
            //You can instantiate your typeface anywhere, I would suggest as a 
            //singleton somewhere to avoid unnecessary copies
            setTypeface(roboto); 
            break;
        case ROBOTO_CONDENSED:
            setTypeface(robotoCondensed);
            break;
    }

    values.recycle();
}

Ahora estás listo. Puede agregar más atributos para casi cualquier cosa (podría agregar otro para typefaceStyle: negrita, cursiva, etc.) pero ahora veamos cómo usarlo:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/com.yourpackage.name"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <com.yourpackage.name.CustomButton
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click Me!"
        custom:typeface="roboto" />

</LinearLayout>

La xmlns:customlínea realmente puede ser cualquier cosa, pero la convención es lo que se muestra arriba. Lo que importa es que es único y por eso se usa el nombre del paquete. Ahora solo usa el custom:prefijo para tus atributos y el android:prefijo para los atributos de Android.

Una última cosa: si quiere utilizar esto en un estilo ( res/values/styles.xml), debe no agregar la xmlns:customlínea. Simplemente haga referencia al nombre del atributo sin prefijo:

<style name="MyStyle>
    <item name="typeface">roboto</item>
</style>

                               (PREVIOUS ANSWER)

Usar un tipo de letra personalizado en Android

Esto debería ayudar. Básicamente, no hay forma de hacer esto en XML, y hasta donde yo sé, no hay una forma más fácil de hacerlo en código. Siempre puede tener un método setLayoutFont () que cree el tipo de letra una vez y luego ejecute setTypeface () para cada uno. Solo tendría que actualizarlo cada vez que agregue un nuevo elemento a un diseño. Algo como a continuación:

public void setLayoutFont() {
    Typeface tf = Typeface.createFromAsset(
        getBaseContext().getAssets(), "fonts/BPreplay.otf");
    TextView tv1 = (TextView)findViewById(R.id.tv1);
    tv1.setTypeface(tf);

    TextView tv2 = (TextView)findViewById(R.id.tv2);
    tv2.setTypeface(tf);

    TextView tv3 = (TextView)findViewById(R.id.tv3);
    tv3.setTypeface(tf);
}

EDITAR : Así que empecé a implementar algo como esto yo mismo, y cómo terminé haciéndolo fue haciendo una función como esta:

public static void setLayoutFont(Typeface tf, TextView...params) {
    for (TextView tv : params) {
        tv.setTypeface(tf);
    }
}

Luego, simplemente use este método de onCreate () y pase todos los TextViews que desea actualizar:

Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/BPreplay.otf");
//find views by id...
setLayoutFont(tf, tv1, tv2, tv3, tv4, tv5);

EDITAR 5/09/12:

Entonces, dado que esto todavía está obteniendo vistas y votos, me gustaría agregar un método mucho mejor y más completo:

Typeface mFont = Typeface.createFromAsset(getAssets(), "fonts/BPreplay.otf");
ViewGroup root = (ViewGroup)findViewById(R.id.myrootlayout);
setFont(root, mFont);

/*
 * Sets the font on all TextViews in the ViewGroup. Searches
 * recursively for all inner ViewGroups as well. Just add a
 * check for any other views you want to set as well (EditText,
 * etc.)
 */
public void setFont(ViewGroup group, Typeface font) {
    int count = group.getChildCount();
    View v;
    for(int i = 0; i < count; i++) {
        v = group.getChildAt(i);
        if(v instanceof TextView || v instanceof Button /*etc.*/)
            ((TextView)v).setTypeface(font);
        else if(v instanceof ViewGroup)
            setFont((ViewGroup)v, font);
    }
}

Si le pasa la raíz de su diseño, buscará de forma recursiva TextViewo Buttonvistas (o cualquier otra que agregue a esa declaración if) dentro de ese diseño, y establecerá la fuente sin que tenga que especificarlas por ID. Por supuesto, esto supone que desea configurar la fuente para cada vista.

Kevin Coppock
fuente
1
No veo ninguna diferencia en su código y mi código, excepto que utilizo el método como método de fábrica para toda la aplicación y su código parece estar escrito para una actividad. PD: es realmente extraño agregar un objeto más para un textView de solo lectura solo para cambiar la fuente. Off Topic: Android realmente debería introducir un mecanismo para buscar una fuente de la carpeta assests e incluirla en R para que se pueda cambiar el tiempo de diseño)
Prasham
1
Supongo que, de manera realista, no hay una gran diferencia aparte de que no crearías el tipo de letra una y otra vez. La idea de Varun de usar un tipo de letra estático haría lo mismo.
Kevin Coppock
1
En caso de que la línea final de su código de ejemplo sea setLayoutFont (tf, tv1, tv2, tv3, tv4, tv5); en lugar de setTypeface (tf, tv1, tv2, tv3, tv4, tv5) ;?
Kyle Clegg
1
¿No deberías recycleel TypedArray values?
CorayThan
1
Si usa Gradle, el espacio de nombres personalizado debe serxmlns:custom="http://schemas.android.com/apk/res-auto"
Jabari
93

Hay una forma bastante sencilla de hacerlo mediante XML. Solo necesita crear su propio widget que amplíe TextView.

Primero, cree un archivo en res / values ​​/ attrs.xml con el siguiente contenido:

<resources>
    <declare-styleable name="TypefacedTextView">
        <attr name="typeface" format="string" />
    </declare-styleable>
</resources>

Después de eso, crea tu widget personalizado:

package your.package.widget;

public class TypefacedTextView extends TextView {

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

        if (fontName != null) {
            Typeface typeface = Typeface.createFromAsset(context.getAssets(), fontName);
            setTypeface(typeface);
        }
    }

}

Como puede ver, el código anterior leerá una fuente dentro de la carpeta assets /. Para este ejemplo, supongo que hay un archivo llamado "custom.ttf" en la carpeta de activos. Por último, use el widget en los XML:

<your.package.widget.TypefacedTextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:your_namespace="http://schemas.android.com/apk/res/your.package"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Custom fonts in XML are easy"
    android:textColor="#FFF"
    android:textSize="14dip"
    your_namespace:typeface="custom.ttf" />

Nota: no podrá ver su fuente personalizada en el editor de diseño de Eclipse. Por eso pongo el isInEditMode()cheque. Pero si ejecuta su aplicación, la fuente personalizada funcionará a la perfección.

¡Espero eso ayude!

leocadiotina
fuente
No probé esto, pero creé un control personalizado extendiendo la TextViewclase; configuró el typefaceen él y usé el control personalizado en el diseño como lo hacemos normalmente y funcionó para mí ... Sin embargo, fue simple que el anterior ...
Mahendra Liya
1
Hice exactamente lo que dijiste. La única diferencia es que hice este componente reutilizable, porque la pregunta es cómo hacerlo a través de XML. De hecho, hay una manera de hacer esto a través de XML y esa es la manera de hacerlo :)
leocadiotine
Código muy fácil de integrar. Esto funciona para mi. Gracias.
Durai
1
Esta debería ser la respuesta aceptada. Bien escrito. ¡Gracias!
Reaz Murshed
1
Amesome, @DominikSuszczewicz! ¿Puedes compartir el código para que pueda actualizar la respuesta?
leocadiotina
15

Ejemplo de TextView con tipo de letra roboto:

attr.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

<declare-styleable name="RobotoTextView">
    <attr name="typeface"/>
</declare-styleable>

<attr name="typeface" format="enum">
    <enum name="roboto_thin" value="0"/>
    <enum name="roboto_thin_italic" value="1"/>
    <enum name="roboto_light" value="2"/>
    <enum name="roboto_light_italic" value="3"/>
    <enum name="roboto_regular" value="4"/>
    <enum name="roboto_italic" value="5"/>
    <enum name="roboto_medium" value="6"/>
    <enum name="roboto_medium_italic" value="7"/>
    <enum name="roboto_bold" value="8"/>
    <enum name="roboto_bold_italic" value="9"/>
    <enum name="roboto_black" value="10"/>
    <enum name="roboto_black_italic" value="11"/>
    <enum name="roboto_condensed" value="12"/>
    <enum name="roboto_condensed_italic" value="13"/>
    <enum name="roboto_condensed_bold" value="14"/>
    <enum name="roboto_condensed_bold_italic" value="15"/>
</attr>

</resources>

RobotoTextView.java:

public class RobotoTextView extends TextView {

/*
 * Permissible values ​​for the "typeface" attribute.
 */
private final static int ROBOTO_THIN = 0;
private final static int ROBOTO_THIN_ITALIC = 1;
private final static int ROBOTO_LIGHT = 2;
private final static int ROBOTO_LIGHT_ITALIC = 3;
private final static int ROBOTO_REGULAR = 4;
private final static int ROBOTO_ITALIC = 5;
private final static int ROBOTO_MEDIUM = 6;
private final static int ROBOTO_MEDIUM_ITALIC = 7;
private final static int ROBOTO_BOLD = 8;
private final static int ROBOTO_BOLD_ITALIC = 9;
private final static int ROBOTO_BLACK = 10;
private final static int ROBOTO_BLACK_ITALIC = 11;
private final static int ROBOTO_CONDENSED = 12;
private final static int ROBOTO_CONDENSED_ITALIC = 13;
private final static int ROBOTO_CONDENSED_BOLD = 14;
private final static int ROBOTO_CONDENSED_BOLD_ITALIC = 15;
/**
 * List of created typefaces for later reused.
 */
private final static SparseArray<Typeface> mTypefaces = new SparseArray<Typeface>(16);

/**
 * Simple constructor to use when creating a view from code.
 *
 * @param context The Context the view is running in, through which it can
 *                access the current theme, resources, etc.
 */
public RobotoTextView(Context context) {
    super(context);
}

/**
 * Constructor that is called when inflating a view from XML. This is called
 * when a view is being constructed from an XML file, supplying attributes
 * that were specified in the XML file. This version uses a default style of
 * 0, so the only attribute values applied are those in the Context's Theme
 * and the given AttributeSet.
 * <p/>
 * <p/>
 * The method onFinishInflate() will be called after all children have been
 * added.
 *
 * @param context The Context the view is running in, through which it can
 *                access the current theme, resources, etc.
 * @param attrs   The attributes of the XML tag that is inflating the view.
 * @see #RobotoTextView(Context, AttributeSet, int)
 */
public RobotoTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    parseAttributes(context, attrs);
}

/**
 * Perform inflation from XML and apply a class-specific base style. This
 * constructor of View allows subclasses to use their own base style when
 * they are inflating.
 *
 * @param context  The Context the view is running in, through which it can
 *                 access the current theme, resources, etc.
 * @param attrs    The attributes of the XML tag that is inflating the view.
 * @param defStyle The default style to apply to this view. If 0, no style
 *                 will be applied (beyond what is included in the theme). This may
 *                 either be an attribute resource, whose value will be retrieved
 *                 from the current theme, or an explicit style resource.
 * @see #RobotoTextView(Context, AttributeSet)
 */
public RobotoTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    parseAttributes(context, attrs);
}

/**
 * Parse the attributes.
 *
 * @param context The Context the view is running in, through which it can access the current theme, resources, etc.
 * @param attrs   The attributes of the XML tag that is inflating the view.
 */
private void parseAttributes(Context context, AttributeSet attrs) {
    TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.RobotoTextView);

    int typefaceValue = values.getInt(R.styleable.RobotoTextView_typeface, 0);
    values.recycle();

    setTypeface(obtaintTypeface(context, typefaceValue));
}

/**
 * Obtain typeface.
 *
 * @param context       The Context the view is running in, through which it can
 *                      access the current theme, resources, etc.
 * @param typefaceValue values ​​for the "typeface" attribute
 * @return Roboto {@link Typeface}
 * @throws IllegalArgumentException if unknown `typeface` attribute value.
 */
private Typeface obtaintTypeface(Context context, int typefaceValue) throws IllegalArgumentException {
    Typeface typeface = mTypefaces.get(typefaceValue);
    if (typeface == null) {
        typeface = createTypeface(context, typefaceValue);
        mTypefaces.put(typefaceValue, typeface);
    }
    return typeface;
}

/**
 * Create typeface from assets.
 *
 * @param context       The Context the view is running in, through which it can
 *                      access the current theme, resources, etc.
 * @param typefaceValue values ​​for the "typeface" attribute
 * @return Roboto {@link Typeface}
 * @throws IllegalArgumentException if unknown `typeface` attribute value.
 */
private Typeface createTypeface(Context context, int typefaceValue) throws IllegalArgumentException {
    Typeface typeface;
    switch (typefaceValue) {
        case ROBOTO_THIN:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Thin.ttf");
            break;
        case ROBOTO_THIN_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-ThinItalic.ttf");
            break;
        case ROBOTO_LIGHT:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Light.ttf");
            break;
        case ROBOTO_LIGHT_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-LightItalic.ttf");
            break;
        case ROBOTO_REGULAR:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Regular.ttf");
            break;
        case ROBOTO_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Italic.ttf");
            break;
        case ROBOTO_MEDIUM:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Medium.ttf");
            break;
        case ROBOTO_MEDIUM_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-MediumItalic.ttf");
            break;
        case ROBOTO_BOLD:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Bold.ttf");
            break;
        case ROBOTO_BOLD_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldItalic.ttf");
            break;
        case ROBOTO_BLACK:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Black.ttf");
            break;
        case ROBOTO_BLACK_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BlackItalic.ttf");
            break;
        case ROBOTO_CONDENSED:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Condensed.ttf");
            break;
        case ROBOTO_CONDENSED_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-CondensedItalic.ttf");
            break;
        case ROBOTO_CONDENSED_BOLD:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldCondensed.ttf");
            break;
        case ROBOTO_CONDENSED_BOLD_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldCondensedItalic.ttf");
            break;
        default:
            throw new IllegalArgumentException("Unknown `typeface` attribute value " + typefaceValue);
    }
    return typeface;
}

}

Ejemplo de uso:

<your.package.widget.RobotoTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:typeface="roboto_thin"
                android:textSize="22sp"
                android:text="Roboto Thin"/>

Recursos: fuentes Roboto y Noto

e.shishkin
fuente
Sin embargo, ¿hay una manera de usar esta solución sin corregir los identificadores de las fuentes en la clase Java? tal vez lea estos campos finales de enum attrs .. private final static int ROBOTO_THIN = 0; privado final estático int ROBOTO_THIN_ITALIC = 1; privado final estático int ROBOTO_LIGHT = 2; ...
Arthur Melo
3

Es demasiado tarde, pero ayuda al otro,
he creado CustomTextView que tiene un atributo llamado typeFace y se ocupa del problema de pérdida de memoria con la carga de tipografía sin almacenamiento en caché

En primer lugar, la Fontsclase que carga las fuentes de los activos solo una vez

 import android.content.Context;
import android.graphics.Typeface;

import java.util.Hashtable;

/**
 * Created by tonyhaddad on 7/19/15.
 */
public class Fonts {
    private Context context;

    public Fonts(Context context) {
        this.context = context;
    }
    private static Hashtable<String, Typeface> sTypeFaces = new Hashtable<String, Typeface>(
            4);
    public static Typeface getTypeFace(Context context, String fileName) {
        Typeface tempTypeface = sTypeFaces.get(fileName);

        if (tempTypeface == null) {
            String fontPath=null;
            if(fileName=="metabold")
                fontPath ="fonts/Meta-Bold.ttf";

            else if(fileName=="metanormal")
                fontPath="fonts/Meta-Normal.ttf";
            else if(fileName=="gsligh")
                fontPath="fonts/gesslight.ttf";
            else if(fileName=="bold")
                fontPath="fonts/Lato-Bold.ttf";
            else if(fileName=="rcr")
                fontPath="fonts/RobotoCondensed-Regular.ttf";

            else if(fileName=="mpr")
                fontPath="fonts/MyriadPro-Regular.otf";
            else if(fileName=="rr")
                fontPath="fonts/Roboto-Regular.ttf";

            tempTypeface = Typeface.createFromAsset(context.getAssets(), fontPath);
            sTypeFaces.put(fileName, tempTypeface);
        }

        return tempTypeface;
    }
}

entonces necesita agregar un atributo personalizado en el attrs.xml agregar esto

<declare-styleable name="CustomFontTextView">
        <attr name="typeFace" format="string" />

    </declare-styleable>

luego clase personalizada

 package package_name;

/**
 * Created by tonyhaddad on 8/26/15.
 */

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

import package_name.R;

public class CustomFontTextView extends TextView {

    String typeFace;


    public CustomFontTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        if (isInEditMode()) {
            return;
        }
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CustomFontTextView,
                0, 0);
        try {
            typeFace = a.getString(0);
        } finally {
            a.recycle();
        }

        if(typeFace!=null && !typeFace.equalsIgnoreCase(""))
        {
            Typeface tf = Fonts.getTypeFace(context, typeFace);
            setTypeface(tf);
        }
        init();
    }

    public CustomFontTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        if (isInEditMode()) {
            return;
        }
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CustomFontTextView,
                0, 0);
        try {
            typeFace = a.getString(0);
        } finally {
            a.recycle();
        }

        if(typeFace!=null && !typeFace.equalsIgnoreCase(""))
        {
            Typeface tf = Fonts.getTypeFace(context, typeFace);
            setTypeface(tf);
        }

        init();
    }

    public CustomFontTextView(Context context) {
        super(context);



        if(typeFace!=null && !typeFace.equalsIgnoreCase(""))
        {
            Typeface tf = Fonts.getTypeFace(context, typeFace);
            setTypeface(tf);
        }
        init();
    }


    private void init() {

    }

    public String getTypeFace() {
        return typeFace;
    }

    public void setTypeFace(String typeFace) {
        this.typeFace = typeFace;
        invalidate();
        requestLayout();
    }
}

y finalmente agregue la vista de texto

  <package_name.CustomFontTextView
            xmlns:custom="http://schemas.android.com/apk/res-auto/package_name"
            android:id="@+id/txt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="41dp"
            android:gravity="center_vertical"
            android:text="text"
            android:textColor="#000"
            android:textSize="23sp"
            custom:typeFace="metanormal"/>

y puede cambiar la fuente de manera programada con el método setTypeFace y
también puede mover el espacio de nombres personalizado a su diseño principal si desea usar más de uno desde esta vista

Codificación feliz :)

Antwan
fuente
respuesta simple y recta.
eyadMhanna
2

El método siguiente, llamado en onCreate () y pasado su ViewGroup más externo, funcionará para todo menos el texto que se crea dinámicamente (es decir, listas dinámicas, alertas, etc.). Una forma fácil de obtener el ViewGroup más externo es usar getRootView en cualquiera de sus vistas.

public void onCreate(Bundle savedInstanceState){
    //onCreate code...
    EditText text = (EditText) findViewById(R.id.editText1);
    setTypeFaceForViewGroup((ViewGroup) text.getRootView());
}

private void setTypeFaceForViewGroup(ViewGroup vg){

    for (int i = 0; i < vg.getChildCount(); i++) {

            if (vg.getChildAt(i) instanceof ViewGroup)
                setTypeFaceForViewGroup((ViewGroup) vg.getChildAt(i));

            else if (vg.getChildAt(i) instanceof TextView)
                ((TextView) vg.getChildAt(i)).setTypeface(Typeface.createFromAsset(getAssets(), "fonts/Your_Font.ttf"));

    }

}

Esto también debería funcionar para contenido dinámico, solo tendría que llamarlo, pasando lo que haya creado, justo después de haberlo creado (aunque no lo he probado).

Para ahorrar memoria, probablemente querrá hacer que el tipo de letra sea una variable estática, en lugar de crear una nueva cada vez que el bucle se ejecute como lo hice aquí.

Chris
fuente
No recomiendo esta solución, porque está creando una nueva instancia de la misma fuente para cada elemento al que desea aplicarla. Esto puede causar problemas de memoria.
flawyte
Eso está cubierto en mi nota al final.
Chris
2

Si está buscando una solución programática más general, creé una clase estática que se puede usar para configurar el tipo de letra de una vista completa (UI de actividad). Tenga en cuenta que estoy trabajando con Mono (C #) pero puede implementarlo fácilmente usando Java.

Puede pasar a esta clase un diseño o una vista específica que desee personalizar. Si quieres ser súper eficiente, puedes implementarlo usando el patrón Singleton.

public static class AndroidTypefaceUtility 
{
    static AndroidTypefaceUtility()
    {
    }
    //Refer to the code block beneath this one, to see how to create a typeface.
    public static void SetTypefaceOfView(View view, Typeface customTypeface)
    {
    if (customTypeface != null && view != null)
    {
            try
            {
                if (view is TextView)
                    (view as TextView).Typeface = customTypeface;
                else if (view is Button)
                    (view as Button).Typeface = customTypeface;
                else if (view is EditText)
                    (view as EditText).Typeface = customTypeface;
                else if (view is ViewGroup)
                    SetTypefaceOfViewGroup((view as ViewGroup), customTypeface);
                else
                    Console.Error.WriteLine("AndroidTypefaceUtility: {0} is type of {1} and does not have a typeface property", view.Id, typeof(View));
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine("AndroidTypefaceUtility threw:\n{0}\n{1}", ex.GetType(), ex.StackTrace);
                    throw ex;
                }
            }
            else
            {
                Console.Error.WriteLine("AndroidTypefaceUtility: customTypeface / view parameter should not be null");
            }
        }

        public static void SetTypefaceOfViewGroup(ViewGroup layout, Typeface customTypeface)
        {
            if (customTypeface != null && layout != null)
            {
                for (int i = 0; i < layout.ChildCount; i++)
                {
                    SetTypefaceOfView(layout.GetChildAt(i), customTypeface);
                }
            }
            else
            {
                Console.Error.WriteLine("AndroidTypefaceUtility: customTypeface / layout parameter should not be null");
            }
        }

    }

En su actividad, deberá crear un objeto Tipo de letra. Creo el mío en OnCreate () usando un archivo .ttf ubicado en mi directorio Resources / Assets /. Asegúrese de que el archivo esté marcado como Activo de Android en sus propiedades.

protected override void OnCreate(Bundle bundle)
{               
    ...
    LinearLayout rootLayout = (LinearLayout)FindViewById<LinearLayout>(Resource.Id.signInView_LinearLayout);
    Typeface allerTypeface = Typeface.CreateFromAsset(base.Assets,"Aller_Rg.ttf");
    AndroidTypefaceUtility.SetTypefaceOfViewGroup(rootLayout, allerTypeface);
}
JCKortlang
fuente
2

Desafortunadamente, Android no proporciona la forma rápida, fácil y limpia que está buscando para cambiar la fuente para toda su aplicación. Pero recientemente analicé este asunto y creé algunas herramientas que le permiten cambiar la fuente sin ningún tipo de codificación (puede hacerlo todo a través de xml, estilos e incluso apariencias de texto). Se basan en soluciones similares a las que ve en las otras respuestas aquí, pero permiten mucha más flexibilidad. Puedes leerlo todo en este blog y ver el proyecto github aquí .

A continuación, se muestra un ejemplo de cómo aplicar estas herramientas. Pon todos tus archivos de fuentes en formato assets/fonts/. Luego, declare esas fuentes en un archivo xml (por ejemplo res/xml/fonts.xml) y cargue este archivo al principio de su aplicación con TypefaceManager.initialize(this, R.xml.fonts);(por ejemplo, en el onCreate de su clase de aplicación). El archivo xml se ve así:

<?xml version="1.0" encoding="utf-8"?>
<familyset>

    <!-- Some Font. Can be referenced with 'someFont' or 'aspergit' -->
    <family>
        <nameset>
            <name>aspergit</name>
            <name>someFont</name>
        </nameset>
        <fileset>
            <file>Aspergit.ttf</file>
            <file>Aspergit Bold.ttf</file>
            <file>Aspergit Italic.ttf</file>
            <file>Aspergit Bold Italic.ttf</file>
        </fileset>
    </family>

    <!-- Another Font. Can be referenced with 'anotherFont' or 'bodoni' -->
    <family>
        <nameset>
            <name>bodoni</name>
            <name>anotherFont</name>
        </nameset>
        <fileset>
            <file>BodoniFLF-Roman.ttf</file>
            <file>BodoniFLF-Bold.ttf</file>
        </fileset>
    </family>

</familyset>

Ahora puede usar estas fuentes en su estilo o xml (siempre que use las herramientas que mencioné anteriormente), usando el elemento de interfaz de usuario personalizado com.innovattic.font.FontTextViewen su diseño xml. A continuación, puede ver cómo puede aplicar una fuente a todos los textos en toda su aplicación, simplemente editando res/values/styles.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">

    <!-- Application theme -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
        <item name="android:textViewStyle">@style/MyTextViewStyle</item>
    </style>

    <!-- Style to use for ALL text views (including FontTextView) -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="MyTextViewStyle" parent="@android:style/Widget.Holo.Light.TextView">
        <item name="android:textAppearance">@style/MyTextAppearance</item>
    </style>

    <!-- Text appearance to use for ALL text views (including FontTextView) -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="MyTextAppearance" parent="@android:style/TextAppearance.Holo">
        <!-- Alternatively, reference this font with the name "aspergit" -->
        <!-- Note that only our own TextView's will use the font attribute -->
        <item name="flFont">someFont</item>
        <item name="android:textStyle">bold|italic</item>
    </style>

    <!-- Alternative style, maybe for some other widget -->
    <style name="StylishFont">
        <item name="flFont">anotherFont</item>
        <item name="android:textStyle">normal</item>
    </style>

</resources>

Con el acompañante res/layout/layout.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <!-- This text view is styled with the app theme -->
    <com.innovattic.font.FontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This uses my font in bold italic style" />

    <!-- This text view is styled here and overrides the app theme -->
    <com.innovattic.font.FontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:flFont="anotherFont"
        android:textStyle="normal"
        android:text="This uses another font in normal style" />

    <!-- This text view is styled with a style and overrides the app theme -->
    <com.innovattic.font.FontTextView
        style="@style/StylishFont"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This also uses another font in normal style" />

</LinearLayout>

No olvide aplicar el tema en su manifiesto de Android.

Jelle Fresen
fuente
2

Me gustaría agregar una nota a la gran solución de leocadiotine. Es perfecto, pero cuando se utiliza este TextView personalizado muchas veces ralentiza la aplicación, ya que tiene que acceder a los activos cada vez que se crea una vista de texto. Sugiero usar algo como View Holder patternen el Adapters, escribí un ejemplo:

public class Fonts {

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

    public static Typeface getTypeface(Context ctx, String fontName) {
        Typeface typeface = typefaces.get(fontName);
        if (typeface == null) {
            typeface = Typeface.createFromAsset(ctx.getAssets(), fontName);
            typefaces.put(fontName, typeface);
        }
        return typeface;
    } 
}

De esta manera, la aplicación accede a los activos solo una vez por activo y los mantiene en la memoria para futuras necesidades.

Emaborsa
fuente
0

No sé si cambia toda la aplicación, pero he logrado cambiar algunos componentes que de otra manera no se podrían cambiar haciendo esto:

Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/Lucida Sans Unicode.ttf");
Typeface.class.getField("DEFAULT").setAccessible(true);
Typeface.class.getField("DEFAULT_BOLD").setAccessible(true);
Typeface.class.getField("DEFAULT").set(null, tf);
Typeface.class.getField("DEFAULT_BOLD").set(null, tf);
Ricardo
fuente
@richard, quiero configurar la fuente personalizada de acuerdo con la configuración regional. Por ejemplo, quiero configurar Arial TTF siempre que usemos la configuración regional en inglés y configurar el TTF gótico cuando utilizo la escala local coreana
Dwivedi Ji
0

He encontrado información paso a paso en este enlace, enlace: https://github.com/jaydipumaretiya/CustomTypeface/

Hay muchas formas de usar el tipo de letra correctamente en Android, debe colocar su archivo de tipo de letra en la carpeta de activos debajo de su principal directamente y puede usarlo en tiempo de ejecución.

Otra forma más sencilla es usar la biblioteca predeterminada para configurar el tipo de letra en su archivo xml. Prefiero esta biblioteca de tipos de letra personalizada para configurar el tipo de letra en TextView, EditText, Button, CheckBox, RadioButton y AutoCompleteTextView y otras cuñas en Android.

Mehul Rakholiya
fuente
El enlace de github no funciona.
Thomas
0

Android 8.0 (API nivel 26) introduce una nueva función, Fuentes en XML. Puede crear un archivo fontfamily y configurarlo en styles.xml.

Para agregar fuentes como recursos, realice los siguientes pasos en Android Studio:

1.Haga clic con el botón derecho en la carpeta res y vaya a Nuevo> Directorio de recursos de Android. Aparece la ventana Nuevo directorio de recursos.

2. En la lista Tipo de recurso, seleccione la fuente y luego haga clic en Aceptar. Nota: El nombre del directorio de recursos debe ser fuente.

3. Agregue sus archivos de fuentes en la carpeta de fuentes.

Para crear una familia de fuentes, realice los siguientes pasos:

1.Haga clic con el botón derecho en la carpeta de fuentes y vaya a Nuevo> Archivo de recursos de fuentes. Aparece la ventana Nuevo archivo de recursos.

2. Ingrese el nombre del archivo y luego haga clic en Aceptar. El nuevo XML de recursos de fuentes se abre en el editor.

3. Incluya cada archivo de fuente, estilo y atributo de peso en el elemento. El siguiente XML ilustra la adición de atributos relacionados con fuentes en el XML de recursos de fuentes:

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

Agregar fuentes al estilo

Abra styles.xml y establezca el atributo fontFamily en el archivo de fuente al que desea acceder.

 <style name="customfontstyle" parent="@android:style/TextAppearance.Small">
    <item name="android:fontFamily">@font/lobster</item>
</style>

Fuente: Fuentes en XML

Desarrollador de Android
fuente