Cómo configurar la familia de fuentes predeterminada para toda la aplicación de Android

283

Estoy usando la fuente Roboto light en mi aplicación. Para configurar la fuente tengo que agregar el android:fontFamily="sans-serif-light"a cada vista. ¿Hay alguna forma de declarar la fuente Roboto como familia de fuentes predeterminada para toda la aplicación? Lo intenté así, pero no pareció funcionar.

<style name="AppBaseTheme" parent="android:Theme.Light"></style>

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:fontFamily">sans-serif-light</item>
</style>
tomrozb
fuente
2
Esto podría ayudarlo: stackoverflow.com/a/16883281/1329733
Jacob R
2
Ahora puede especificar fuentes personalizadas directamente desde el XML en android studio 3.0 developer.android.com/guide/topics/ui/look-and-feel/…
Siete

Respuestas:

289

La respuesta es sí.

Luz global Roboto para TextViewy Buttonclases:

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:textViewStyle">@style/RobotoTextViewStyle</item>
    <item name="android:buttonStyle">@style/RobotoButtonStyle</item>
</style>

<style name="RobotoTextViewStyle" parent="android:Widget.TextView">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

<style name="RobotoButtonStyle" parent="android:Widget.Holo.Button">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

Simplemente seleccione el estilo que desee de la lista themes.xml , luego cree su estilo personalizado basado en el original. Al final, aplique el estilo como tema de la aplicación.

<application
    android:theme="@style/AppTheme" >
</application>

Funcionará solo con fuentes incorporadas como Roboto, pero esa era la pregunta. Para fuentes personalizadas (cargadas de activos, por ejemplo), este método no funcionará.

EDITAR 13/08/15

Si está utilizando temas de AppCompat, recuerde eliminar el android:prefijo. Por ejemplo:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:textViewStyle">@style/RobotoTextViewStyle</item>
    <item name="buttonStyle">@style/RobotoButtonStyle</item>
</style>

Tenga en cuenta buttonStyleque no contiene el android:prefijo, pero textViewStyledebe contenerlo.

tomrozb
fuente
44
¿De dónde sacaste el sans-serif-lightvalor? ¿Hay una lista de valores válidos para fontFamilyalgún lugar? He estado revisando los documentos, así como los archivos de tema y estilo en la fuente de Android y no puedo encontrar nada.
Christopher Perry
34
esto es posible solo para el nivel 16 de API ... el nombre "android: fontFamily" existe solo en el nivel 16 o superior ... ¿hay alguna manera de hacerlo también para API 14, por ejemplo?
Lorenzo Barbagli
3
@LorenzoBarbagli, puedes revisar Caligrafía
Brais Gabin
10
Bueno, ¿qué hago si tengo una fuente personalizada?
Rohit Tigga
2
Sí, también quiero agregar una fuente personalizada a toda la aplicación. Cómo puedo hacer eso ?. ¿Debo anular TextView y reemplazar todo TextView como se sugiere en la primera respuesta
John
145

Con el lanzamiento de Android Oreo, puede utilizar la biblioteca de soporte para alcanzar este objetivo.

  1. Compruebe en su aplicación build.gradle si tiene la biblioteca de soporte > = 26.0.0
  2. Agregue la carpeta " fuente " a su carpeta de recursos y agregue sus fuentes allí
  3. Consulte su familia de fuentes predeterminada en el estilo principal de su aplicación:

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
       <item name="android:fontFamily">@font/your_font</item>
       <item name="fontFamily">@font/your_font</item> <!-- target android sdk versions < 26 and > 14 if theme other than AppCompat -->
    </style>

Consulte https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html para obtener información más detallada.

João Magalhães
fuente
9
Al apuntar a API 26+, este debería ser el método aceptado. Cuando se utiliza la biblioteca de compatibilidad , simplemente quitar el android:prefijo
webo80
2
si usa solo la versión no prefijada, está bien. El prefijo simplemente será ignorado en API <26
webo80
2
Esto no establece la fuente en todas partes ... por ejemplo, si tiene estilos derivados Base.TextAppearance.AppCompat, no se usa allí.
Ixx
3
@ Ixx, ¿cómo anular esos estilos también?
Primož Kralj
2
Recuerde usar también AppCompatTextView cuando apunte a api <26
Codelicious
38

Para cambiar la fuente de su aplicación, siga los siguientes pasos:

  1. Dentro del resdirectorio crea un nuevo directorio y llámalo font.
  2. Inserte su fuente .ttf / .otf dentro de la carpeta de fuentes, asegúrese de que el nombre de la fuente sea minúscula y solo subrayado.
  3. Inside res-> values-> styles.xmlinside <resources>-> <style>agrega tu fuente <item name="android:fontFamily">@font/font_name</item>.

ingrese la descripción de la imagen aquí

Ahora todo el texto de su aplicación debe estar en la fuente que agregue.

chico
fuente
8
mientras uso fuentes personalizadas, ¿cómo puedo agregar fuentes en negrita junto con las fuentes normales?
Rajbir Shienh
Eso funciona solo con API nivel 26 y superior, ¿qué pasa con API 21 y inferior?
zulkarnain shah
34

LEER ACTUALIZACIONES A CONTINUACIÓN

Tuve el mismo problema con la incrustación de una nueva fuente y finalmente conseguí que funcionara extendiendo TextView y configurando la fuente tipográfica dentro.

public class YourTextView extends TextView {

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

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

    public YourTextView(Context context) {
        super(context);
        init();
    }

    private void init() {
        Typeface tf = Typeface.createFromAsset(context.getAssets(),
            "fonts/helveticaneue.ttf");
        setTypeface(tf);
    }
}

Debe cambiar los Elementos TextView más tarde de a en cada elemento. Y si usa el UI-Creator en Eclipse, a veces no muestra las TextViews correctamente. Fue lo único que funcionó para mí ...

ACTUALIZAR

Hoy en día estoy usando la reflexión para cambiar los tipos de letra en toda la aplicación sin extender TextViews. Mira esta publicación SO

ACTUALIZACIÓN 2

A partir del nivel de API 26 y disponible en 'biblioteca de soporte', puede usar

android:fontFamily="@font/embeddedfont"

Más información: Fuentes en XML

longi
fuente
25
Esta no es la solución. Estoy usando muchas vistas diferentes, no solo TextView. Quiero configurar la fuente una vez y olvidarme de ella. Además, su código crea un nuevo objeto para cada TextView. Al menos declare el campo como estático para cargar la fuente de los activos una vez.
tomrozb
2
... bueno, hay una función de buscar y reemplazar, que funciona muy bien en este caso
longi
1
Esto no va a funcionar. No puede llamar getContext()cuando la variable es estática. Debería implementarlo de manera única, de lo contrario, el código actual ni siquiera se compilará.
tomrozb
1
Revertí la última confirmación.
Longi
1
@tomrozb: ¡Acabo de darme cuenta de que los últimos cambios rápidos que hice fueron por tus comentarios! Como tiene suficientes puntos, puede optimizar el ejemplo de código usted mismo. de lo contrario, seguiremos hablando del tema en unos años, cuando a nadie le importen los teléfonos inteligentes;)
longi
9

Agregue esta línea de código en su res / value / styles.xml

<item name="android:fontFamily">@font/circular_medium</item>

todo el estilo se verá así

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:fontFamily">@font/circular_medium</item>
</style>

cambie "circular_medium" a su propio nombre de fuente.

nirazverma
fuente
6

No hablemos de rendimiento, para fuentes personalizadas puede tener un método recursivo en bucle a través de todas las vistas y establecer el tipo de letra si es TextView:

public class Font {
    public static void setAllTextView(ViewGroup parent) {
        for (int i = parent.getChildCount() - 1; i >= 0; i--) {
            final View child = parent.getChildAt(i);
            if (child instanceof ViewGroup) {
                setAllTextView((ViewGroup) child);
            } else if (child instanceof TextView) {
                ((TextView) child).setTypeface(getFont());
            }
        }
    }

    public static Typeface getFont() {
        return Typeface.createFromAsset(YourApplicationContext.getInstance().getAssets(), "fonts/whateverfont.ttf");
    }
}

En toda su actividad, pásele ViewGroup actual después de setContentView y listo:

ViewGroup group = (ViewGroup) getWindow().getDecorView().findViewById(android.R.id.content);
Font.setAllTextView(group);

Por fragmento puedes hacer algo similar.

Allen Chan
fuente
1
Suena genial pero se pregunta cómo hacer que funcione en los contenidos de recyclerView.
Srujan Barai
Acabo de intentar esto. Demasiado pesado para renderizar. Disminuyendo la velocidad recyclerViewcomo el infierno.
Srujan Barai
Totalmente no recomendado para ninguna vista de lista, este truco es solo para ahorrar tiempo para codificar la vista estática.
Allen Chan
5

Otra forma de hacer esto para toda la aplicación es usar la reflexión basada en esta respuesta

public class TypefaceUtil {
    /**
     * Using reflection to override default typefaces
     * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE
     * OVERRIDDEN
     *
     * @param typefaces map of fonts to replace
     */
    public static void overrideFonts(Map<String, Typeface> typefaces) {
        try {
            final Field field = Typeface.class.getDeclaredField("sSystemFontMap");
            field.setAccessible(true);
            Map<String, Typeface> oldFonts = (Map<String, Typeface>) field.get(null);
            if (oldFonts != null) {
                oldFonts.putAll(typefaces);
            } else {
                oldFonts = typefaces;
            }
            field.set(null, oldFonts);
            field.setAccessible(false);
        } catch (Exception e) {
            Log.e("TypefaceUtil", "Can not set custom fonts");
        }
    }

    public static Typeface getTypeface(int fontType, Context context) {
        // here you can load the Typeface from asset or use default ones
        switch (fontType) {
            case BOLD:
                return Typeface.create(SANS_SERIF, Typeface.BOLD);
            case ITALIC:
                return Typeface.create(SANS_SERIF, Typeface.ITALIC);
            case BOLD_ITALIC:
                return Typeface.create(SANS_SERIF, Typeface.BOLD_ITALIC);
            case LIGHT:
                return Typeface.create(SANS_SERIF_LIGHT, Typeface.NORMAL);
            case CONDENSED:
                return Typeface.create(SANS_SERIF_CONDENSED, Typeface.NORMAL);
            case THIN:
                return Typeface.create(SANS_SERIF_MEDIUM, Typeface.NORMAL);
            case MEDIUM:
                return Typeface.create(SANS_SERIF_THIN, Typeface.NORMAL);
            case REGULAR:
            default:
                return Typeface.create(SANS_SERIF, Typeface.NORMAL);
        }
    }
}

luego, cuando desee anular las fuentes, puede llamar al método y asignarle un mapa de tipos de letra de la siguiente manera:

Typeface regular = TypefaceUtil.getTypeface(REGULAR, context);
Typeface light = TypefaceUtil.getTypeface(REGULAR, context);
Typeface condensed = TypefaceUtil.getTypeface(CONDENSED, context);
Typeface thin = TypefaceUtil.getTypeface(THIN, context);
Typeface medium = TypefaceUtil.getTypeface(MEDIUM, context);
Map<String, Typeface> fonts = new HashMap<>();
fonts.put("sans-serif", regular);
fonts.put("sans-serif-light", light);
fonts.put("sans-serif-condensed", condensed);
fonts.put("sans-serif-thin", thin);
fonts.put("sans-serif-medium", medium);
TypefaceUtil.overrideFonts(fonts);

para ver el ejemplo completo

Esto solo funciona para Android SDK 21 y superior para versiones anteriores, consulte el ejemplo completo

Ismail Almetwally
fuente
5

Simplemente use esta lib compílela en su archivo de calificación

complie'me.anwarshahriar:calligrapher:1.0'

y usarlo en el método onCreate en la actividad principal

Calligrapher calligrapher = new Calligrapher(this);
calligrapher.setFont(this, "yourCustomFontHere.ttf", true);

Esta es la forma súper rápida más elegante de hacer eso.

Mohamed Ayed
fuente
2

Este es el trabajo para mi proyecto, fuente https://gist.github.com/artem-zinnatullin/7749076

Cree el directorio de fuentes dentro de la Carpeta de activos y luego copie su fuente personalizada al directorio de fuentes, por ejemplo, estoy usando trebuchet.ttf;

Crear una clase TypefaceUtil.java;

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

import java.lang.reflect.Field;
public class TypefaceUtil {

    public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) {
        try {
            final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets);

            final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);
            defaultFontTypefaceField.setAccessible(true);
            defaultFontTypefaceField.set(null, customFontTypeface);
        } catch (Exception e) {

        }
    }
}

Editar tema en styles.xml agregar a continuación

<item name="android:typeface">serif</item>

Ejemplo en Mis estilos.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:typeface">serif</item><!-- Add here -->
    </style>


    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:windowFullscreen">true</item>
    </style>
</resources>

Finalmente, en Activity or Fragment onCreate call TypefaceUtil.java

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TypefaceUtil.overrideFont(getContext(), "SERIF", "fonts/trebuchet.ttf");
    }
Irvan Dwi Pangga
fuente
0

Android no ofrece mucho soporte para la aplicación de fuentes en toda la aplicación (consulte este problema ). Tiene 4 opciones para configurar la fuente para toda la aplicación:

  • Opción 1: aplicar reflejo para cambiar la fuente del sistema
  • Opción 2: crear y subclasificar clases de vista personalizadas para cada vista que necesita una fuente personalizada
  • Opción 3: Implemente un rastreador de vistas que atraviese la jerarquía de vistas para la pantalla actual
  • Opción 4: usar una biblioteca de terceros.

Los detalles de estas opciones se pueden encontrar aquí .

Phileo99
fuente
0

Sé que esta pregunta es bastante antigua, pero he encontrado una buena solución. Básicamente, pasa un diseño de contenedor a esta función, y aplicará la fuente a todas las vistas admitidas, y hará un ciclo recursivo en diseños secundarios:

public static void setFont(ViewGroup layout)
{
    final int childcount = layout.getChildCount();
    for (int i = 0; i < childcount; i++)
    {
        // Get the view
        View v = layout.getChildAt(i);

        // Apply the font to a possible TextView
        try {
            ((TextView) v).setTypeface(MY_CUSTOM_FONT);
            continue;
        }
        catch (Exception e) { }

        // Apply the font to a possible EditText
        try {
            ((TextView) v).setTypeface(MY_CUSTOM_FONT);
            continue;
        }
        catch (Exception e) { }

        // Recursively cicle into a possible child layout
        try {
            ViewGroup vg = (ViewGroup) v;
            Utility.setFont(vg);
            continue;
        }
        catch (Exception e) { }
    }
}
FonzTech
fuente
0

a simple conjunto de tipo de letra de aplicación a normal, sans, serifo monospace(no a una fuente personalizada!), se puede hacer esto.

defina un tema y establezca el android:typefaceatributo en el tipo de letra que desea usar en styles.xml:

<resources>

    <!-- custom normal activity theme -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <!-- other elements -->
        <item name="android:typeface">monospace</item>
    </style>

</resources>

aplicar el tema a toda la aplicación en el AndroidManifest.xmlarchivo:

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application
        android:theme="@style/AppTheme" >
    </application>
</manifest>

referencia de Android

Eric
fuente
¿Seguro que funciona? Según el documento de Android: "Debe ser uno de los siguientes valores constantes: normal, sans, serif, monospace".
tomrozb
1
Oh, ya veo ... tienes razón ... no entendí la pregunta después de todo: x Solo quería tener toda mi aplicación para usar una fuente monoespaciada (no personalizada) y vi que funcionaba, así que publiqué esto aquí ......... creo que mi respuesta aún podría ser útil para otros que quieran hacer algo similar ... así que lo editaré y lo dejaré aquí ..... estoy bien, ¿está bien? Acumula votos. gracias por señalar eso
Eric
Hola @Dave Cruise, ¿solo funciona para el monoespacio? Solo lo he probado para monoespacio ... y nada más ... así que no estoy seguro ... pero de acuerdo con la documentación, debería funcionar para "normal", "sans" y "serif" también ... . Creo que el tipo de letra es más general que la fuente, por lo que no podemos usarlo para establecer la fuente de la aplicación en una fuente específica como "consolas" o algo así.
Eric
@Eric sí. No tengo idea también. El monoespacio funciona a las mil maravillas, pero no hay suerte para lo normal, sin serif.
Dave Cruise
0

Pruebe esta biblioteca, es ligera y fácil de implementar.

https://github.com/sunnag7/FontStyler

<com.sunnag.fontstyler.FontStylerView
              android:textStyle="bold"
              android:text="@string/about_us"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:paddingTop="8dp"
              app:fontName="Lato-Bold"
              android:textSize="18sp"
              android:id="@+id/textView64" />
Sanny Nagveker
fuente
-7

La respuesta es no, no puedes. Ver ¿Es posible establecer una fuente personalizada para toda la aplicación? para más información.

Hay soluciones, pero nada en las líneas de "una sola línea de código aquí y todas mis fuentes serán esto lugar de eso ".

(Agradezco a Google -y a Apple- por eso). Las fuentes personalizadas tienen un lugar, pero hacerlas fáciles de reemplazar en toda la aplicación, habría creado un mundo entero de aplicaciones Comic Sans )

Martin Marconcini
fuente
41
Completamente en desacuerdo con su comentario. Establecer una fuente globalmente debería ser algo trivial, no algo que requiera los tipos de soluciones necesarias. Depende de los desarrolladores / diseñadores del mundo evitar las aplicaciones "Comic Sans", no Google / Apple para hacer cumplir eso.
LocalPCGuy
44
Consistencia> Diseño elegante.
Martin Marconcini
14
Sin embargo, consistencia <funcionalidad. Desarrollamos aplicaciones que muestran hebreo bíblico. Todas las fuentes de valores que se encuentran en los dispositivos Android (incluidas las últimas fuentes de Android L) hacen un trabajo abismal de renderizar las marcas de cantillation (y hacen un trabajo mediocre en las vocales, de hecho, aunque están mejorando). Necesitamos absolutamente usar una fuente personalizada en toda nuestra aplicación, y hemos tenido que escribir demasiado código simplemente para obtener todas las vistas necesarias para usarlo.
Ted Hopp