Come impostare la famiglia di caratteri predefinita per l'intera app Android


282

Sto usando il carattere leggero Roboto nella mia app. Per impostare il carattere devo aggiungere il android:fontFamily="sans-serif-light"ad ogni vista. Esiste un modo per dichiarare il carattere Roboto come famiglia di caratteri predefinito per l'intera app? Ho provato in questo modo ma non sembra funzionare.

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

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

2
Questo potrebbe esserti utile: stackoverflow.com/a/16883281/1329733
Jacob R

2
Ora puoi specificare caratteri personalizzati direttamente dall'XML in android studio 3.0 developer.android.com/guide/topics/ui/look-and-feel/…
Seven

Risposte:


289

La risposta è si.

Luce globale Roboto per TextViewe Buttonclassi:

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

Basta selezionare lo stile desiderato dall'elenco themes.xml , quindi creare il proprio stile personalizzato basato su quello originale. Alla fine, applica lo stile come tema dell'applicazione.

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

Funzionerà solo con caratteri integrati come Roboto, ma questa era la domanda. Per i caratteri personalizzati (caricati ad esempio dalle risorse) questo metodo non funzionerà.

MODIFICA 13/08/15

Se stai usando temi AppCompat, ricorda di rimuovere il android:prefisso. Per esempio:

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

Nota buttonStyleche non contiene android:prefisso, ma textViewStyledeve contenerlo.


4
Da dove hai preso il sans-serif-lightvalore? C'è un elenco di valori validi per fontFamilyqualche posto? Ho esaminato i documenti, i temi e i file di stile nella fonte Android e non sono riuscito a trovare nulla.
Christopher Perry,

34
questo è possibile solo per API livello 16 .. il nome "android: fontFamily" esiste solo a livello 16 o superiore .. c'è un modo per farlo anche per API 14, ad esempio?
Lorenzo Barbagli,

3
@LorenzoBarbagli, puoi controllare Calligrafia
Brais Gabin,

10
Bene, cosa devo fare se ho un carattere personalizzato?
Rohit Tigga,

2
sì, voglio anche aggiungere un carattere personalizzato all'intera app. Come lo posso fare ?. Devo sovrascrivere TextView e sostituire tutto TextView come suggerito nella prima risposta
John,

145

Con il rilascio di Android Oreo è possibile utilizzare la libreria di supporto per raggiungere questo obiettivo.

  1. Controlla nella tua app build.gradle se hai la libreria di supporto > = 26.0.0
  2. Aggiungi la cartella " font " alla cartella delle risorse e aggiungi i font lì
  3. Fai riferimento alla tua famiglia di caratteri predefinita nello stile principale dell'app:

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

Controlla https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html per informazioni più dettagliate.


9
Quando si sceglie come target l'API 26+, questo dovrebbe essere il metodo accettato. Quando si utilizza la libreria di supporto , è sufficiente rimuovere il android:prefisso
webo80

2
se usi solo la versione non prefissata, va bene. Quello con il prefisso verrà ignorato
sull'API

2
Questo non imposta il carattere dappertutto ... ad esempio se hai stili che derivano Base.TextAppearance.AppCompat, non viene utilizzato lì.
Ixx,

3
@Ixx, come sovrascrivere anche quegli stili?
Primož Kralj,

2
Ricorda di utilizzare anche AppCompatTextView quando scegli come target api <26
Codelicious

37

Per modificare il carattere dell'app, attenersi alla seguente procedura:

  1. All'interno della resdirectory creare una nuova directory e chiamarla font.
  2. Inserisci il tuo carattere .ttf / .otf all'interno della cartella dei caratteri, assicurati che il nome del carattere sia composto da lettere minuscole e sia sottolineato solo.
  3. Interno res-> values-> styles.xmlinterno <resources>-> <style>aggiungi il tuo carattere <item name="android:fontFamily">@font/font_name</item>.

inserisci qui la descrizione dell'immagine

Ora tutto il testo della tua app dovrebbe essere nella fonte che aggiungi.


8
durante l'utilizzo di caratteri personalizzati come posso aggiungere caratteri in grassetto insieme a caratteri normali?
Rajbir Shienh,

Funziona solo con API di livello 26 e superiore, e API 21 e inferiori?
zulkarnain shah

34

LEGGI AGGIORNAMENTI QUI SOTTO

Ho avuto lo stesso problema con l'incorporamento di un nuovo carattere e alla fine ho funzionato con l'estensione di TextView e l'inserimento di typefont all'interno.

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

È necessario modificare gli elementi TextView in seguito in da a in ogni elemento. E se usi UI-Creator in Eclipse, a volte non mostra correttamente le TextView. Era l'unica cosa che funzionava per me ...

AGGIORNARE

Oggi sto usando la reflection per modificare i caratteri tipografici nell'intera applicazione senza estendere TextViews. Dai un'occhiata a questo post SO

AGGIORNAMENTO 2

A partire dal livello API 26 e disponibile nella "libreria di supporto" è possibile utilizzare

android:fontFamily="@font/embeddedfont"

Ulteriori informazioni: caratteri in XML


25
Questa non è la soluzione. Sto usando molte viste diverse, non solo TextView. Voglio impostare il carattere una volta e non pensarci più. Inoltre, il codice crea un nuovo oggetto per ogni TextView. Almeno dichiarare il campo come statico per caricare il carattere dagli asset una volta.
tomrozb,

2
... beh, c'è una funzione trova e sostituisci, che funziona davvero bene in questo caso
longi

1
Questo non funzionerà. Non è possibile chiamare getContext()quando la variabile è statica. Dovresti implementarlo in modo singleton, altrimenti il ​​codice corrente non verrà nemmeno compilato.
tomrozb,

1
ho ripristinato l'ultimo commit.
Longi,

1
@tomrozb: D mi sono appena reso conto che gli ultimi rapidi cambiamenti che ho fatto sono stati a causa dei tuoi commenti! poiché hai abbastanza punti, puoi ottimizzare tu stesso l'esempio di codice. altrimenti parleremo ancora dell'argomento tra qualche anno, quando a nessuno importa più degli smartphone;)
longi

8

Aggiungi questa riga di codice nel tuo res / value / styles.xml

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

l'intero stile sarà simile a quello

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

cambia "circular_medium" con il tuo nome di carattere ..


6

Non parliamo di prestazioni, per un carattere personalizzato puoi avere un metodo ricorsivo che scorre attraverso tutte le viste e imposta il carattere tipografico se è un 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");
    }
}

In tutte le tue attività, passa al ViewGroup corrente dopo setContentView ed è fatto:

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

Per frammento puoi fare qualcosa di simile.


1
Sembra fantastico ma ti stai chiedendo come farlo funzionare nei contenuti di recyclerView?
Srujan Barai,

Ho appena provato questo. troppo pesante per il rendering. Rallentando recyclerViewcome l'inferno.
Srujan Barai,

Totalmente sconsigliato per qualsiasi visualizzazione elenco, questo trucco è solo per risparmiare tempo per codificare la visualizzazione statica.
Allen Chan,

5

Un altro modo per farlo per l'intera app è usare la riflessione basata su questa risposta

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

quindi ogni volta che vuoi sovrascrivere i caratteri puoi semplicemente chiamare il metodo e dargli una mappa di caratteri tipografici come segue:

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

per un controllo completo di esempio

Questo funziona solo per Android SDK 21 e versioni successive per le versioni precedenti controlla l'esempio completo


5

Basta usare questa lib compilarla nel tuo file di valutazione

complie'me.anwarshahriar:calligrapher:1.0'

e utilizzarlo nel metodo onCreate nell'attività principale

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

Questo è il modo più veloce ed elegante per farlo.


2

Questo è un lavoro per il mio progetto, fonte https://gist.github.com/artem-zinnatullin/7749076

Crea la directory dei caratteri all'interno della Cartella risorse e quindi copia il tuo carattere personalizzato nella directory dei caratteri, ad esempio sto usando trebuchet.ttf;

Crea una classe 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) {

        }
    }
}

Modifica tema in styles.xml aggiungi sotto

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

Esempio in My styles.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>

Infine, in Activity o Fragment onCreate chiama TypefaceUtil.java

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

0

Android non fornisce molto in termini di supporto per l'applicazione di caratteri nell'intera app (vedi questo problema ). Hai 4 opzioni per impostare il carattere per l'intera app:

  • Opzione 1: applica la riflessione per modificare il carattere del sistema
  • Opzione2: creare e sottoclassare le classi di visualizzazione personalizzate per ciascuna vista che necessita di un carattere personalizzato
  • Opzione 3: implementare un crawler di visualizzazione che attraversa la gerarchia di visualizzazione per la schermata corrente
  • Opzione 4: utilizzare una libreria di terze parti.

I dettagli di queste opzioni sono disponibili qui .


0

So che questa domanda è piuttosto vecchia, ma ho trovato una buona soluzione. Fondamentalmente, si passa un layout contenitore a questa funzione e si applicherà il carattere a tutte le viste supportate e ciclicamente ricorsivamente nei layout figlio:

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

0

a carattere meramente serie di app per normal, sans, serifo monospace(non un carattere personalizzato!), si può fare questo.

definire un tema e impostare l' android:typefaceattributo sul carattere tipografico che si desidera utilizzare in 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>

applica il tema all'intera app nel AndroidManifest.xmlfile:

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

riferimento Android


Sicuro che funzioni? Secondo il documento Android: "Deve essere uno dei seguenti valori costanti: normale, sans, serif, monospace".
Tomrozb,

1
Oh capisco ... hai ragione ... dopo tutto non ho capito la domanda: x volevo solo avere tutta la mia app per usare un carattere monospace (non personalizzato) e l'ho visto funzionare quindi ho pubblicato questo qui ......... penso che la mia risposta possa ancora essere utile per gli altri che vogliono fare qualcosa di simile .... quindi lo modificherò e lo lascerò qui ..... sono ok è vero accumula voti negativi. grazie per averlo sottolineato
Eric

Ehi @Dave Cruise, funziona solo per monospace? L'ho testato solo per monospace ... e nient'altro .... quindi non ne sono sicuro ... ma secondo la documentazione, dovrebbe funzionare anche per "normale", "sans" e "serif" .. .io penso che il carattere tipografico sia più generale del carattere, quindi non possiamo usarlo per impostare il carattere dell'app su un carattere specifico come "console" o qualcosa del genere.
Eric

@Eric sì. non ne ho idea. il monospazio funziona come un incantesimo ma senza fortuna per normale, sans o serif.
Dave Cruise,

0

Prova questa libreria, è leggera e facile da implementare

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" />

-7

La risposta è no, non puoi. Vedi È possibile impostare un carattere personalizzato per l'intera applicazione? per maggiori informazioni.

Ci sono soluzioni alternative, ma nulla nelle righe di "una singola riga di codice qui e tutti i miei caratteri saranno questo invece di quello ".

(Ringrazio Google e Apple per questo). I caratteri personalizzati hanno un posto, ma rendendoli facili da sostituire a livello di app, avrebbero creato un intero mondo di applicazioni Comic Sans )


41
Completamente in disaccordo con il tuo commento. L'impostazione di un carattere a livello globale dovrebbe essere banale da fare, non qualcosa che richiede i tipi di soluzioni alternative necessarie. Spetta agli sviluppatori / designer di tutto il mondo evitare le applicazioni "Comic Sans", non Google / Apple, per imporlo.
LocalPC Acquista

4
Coerenza> Fantasia.
Martin Marconcini,

14
Tuttavia, coerenza <funzionalità. Sviluppiamo app che mostrano l'ebraico biblico. Tutti i tipi di carattere stock trovati sui dispositivi Android (inclusi gli ultimi caratteri Android L) svolgono un abissale lavoro di rendering dei segni di cantillazione (e fanno un lavoro mediocre sui segni vocalici, del resto, anche se stanno migliorando). Dobbiamo assolutamente utilizzare un carattere personalizzato in tutta la nostra app e abbiamo dovuto scrivere troppi codici semplicemente per ottenere tutte le viste necessarie che lo utilizzano.
Ted Hopp,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.