So legen Sie die Standardschriftfamilie für die gesamte Android-App fest

282

Ich verwende die Roboto Light-Schriftart in meiner App. Um die Schriftart einzustellen, muss ich android:fontFamily="sans-serif-light"sie jeder Ansicht hinzufügen . Gibt es eine Möglichkeit, die Roboto-Schriftart als Standardschriftfamilie für die gesamte App zu deklarieren? Ich habe es so versucht, aber es schien nicht zu funktionieren.

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

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:fontFamily">sans-serif-light</item>
</style>
Tomrozb
quelle
2
Dies könnte Ihnen helfen: stackoverflow.com/a/16883281/1329733
Jacob R
2
Sie können jetzt benutzerdefinierte Schriftarten direkt aus dem XML in Android Studio 3.0 Developer
Sieben

Antworten:

289

Die Antwort ist ja.

Globales Roboto-Licht für TextViewund ButtonKlassen:

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

Wählen Sie einfach den gewünschten Stil aus der Liste theme.xml aus und erstellen Sie Ihren benutzerdefinierten Stil basierend auf dem ursprünglichen. Wenden Sie am Ende den Stil als Thema der Anwendung an.

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

Es funktioniert nur mit eingebauten Schriftarten wie Roboto, aber das war die Frage. Bei benutzerdefinierten Schriftarten (z. B. aus Assets geladen) funktioniert diese Methode nicht.

EDIT 13.08.15

Wenn Sie AppCompat-Designs verwenden, müssen Sie das android:Präfix entfernen . Zum Beispiel:

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

Beachten Sie, dass das Präfix buttonStylekein android:Präfix enthält , es aber textViewStyleenthalten muss.

Tomrozb
quelle
4
Woher haben Sie den sans-serif-lightWert? Gibt es fontFamilyirgendwo eine Liste gültiger Werte ? Ich habe die Dokumente sowie die Themen- und Stildateien in der Android-Quelle durchgesehen und kann nichts finden.
Christopher Perry
34
Dies ist nur für API Level 16 möglich. Der Name "android: fontFamily" existiert nur in Level 16 oder höher. Gibt es eine Möglichkeit, dies auch für API 14 zu tun?
Lorenzo Barbagli
3
@ LorenzoBarbagli, können Sie Kalligraphie
Brais Gabin
10
Was mache ich, wenn ich eine benutzerdefinierte Schriftart habe?
Rohit Tigga
2
Ja, ich möchte der gesamten App auch eine benutzerdefinierte Schriftart hinzufügen. Wie kann ich das machen ?. Muss ich TextView überschreiben und alle TextView ersetzen, wie in der ersten Antwort vorgeschlagen
John
144

Mit der Veröffentlichung von Android Oreo können Sie die Support-Bibliothek verwenden, um dieses Ziel zu erreichen.

  1. Überprüfen Sie in Ihrer App build.gradle, ob Sie die Support-Bibliothek > = 26.0.0 haben
  2. Fügen Sie Ihrem Ressourcenordner den Ordner " font " hinzu und fügen Sie dort Ihre Schriftarten hinzu
  3. Verweisen Sie auf Ihre Standardschriftfamilie im Hauptstil Ihrer 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>

Weitere Informationen finden Sie unter https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html .

João Magalhães
quelle
9
Wenn Sie auf API 26+ abzielen, sollte dies die akzeptierte Methode sein. Wenn Sie die Support Library verwenden , entfernen Sie einfach das android:Präfix
webo80
2
Wenn Sie nur die nicht festgelegte Version verwenden, ist dies in Ordnung. Das vorangestellte wird nur auf API <26
webo80
2
Dies setzt die Schriftart nicht überall ... z. B. wenn Sie Stile haben, von denen abgeleitet ist Base.TextAppearance.AppCompat, wird sie dort nicht verwendet.
Ixx
3
@Ixx, wie kann man diese Stile auch überschreiben?
Primož Kralj
2
Denken Sie daran, AppCompatTextView auch zu verwenden, wenn Sie auf API <26
Codelicious abzielen
37

Gehen Sie folgendermaßen vor, um die Schriftart Ihrer App zu ändern:

  1. Innerhalb des resVerzeichnisses erstellen Sie ein neues Verzeichnis und rufen Sie es auf font.
  2. Fügen Sie Ihre Schriftart .ttf / .otf in den Schriftartenordner ein. Stellen Sie sicher, dass der Schriftname nur aus Kleinbuchstaben und Unterstrichen besteht.
  3. Innen res-> values-> styles.xmlinnen <resources>-><style> Fügen Sie Ihre Schriftart hinzu <item name="android:fontFamily">@font/font_name</item>.

Geben Sie hier die Bildbeschreibung ein

Jetzt sollte sich Ihr gesamter App-Text in der Quelle befinden, die Sie hinzufügen.

Kerl
quelle
8
Wie kann ich bei Verwendung benutzerdefinierter Schriftarten neben normalen Schriftarten auch fette Schriftarten hinzufügen?
Rajbir Shienh
Das funktioniert nur mit API Level 26 und höher. Was ist mit API 21 und niedriger?
Zulkarnain Shah
34

UPDATES UNTEN LESEN

Ich hatte das gleiche Problem beim Einbetten einer neuen Schriftart und brachte sie schließlich dazu, die Textansicht zu erweitern und die Schriftart darin festzulegen.

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

Sie müssen die TextView-Elemente später in jedem Element von von nach ändern. Und wenn Sie den UI-Creator in Eclipse verwenden, zeigt er manchmal die TextViews nicht richtig an. War das einzige was für mich funktioniert ...

AKTUALISIEREN

Heutzutage verwende ich Reflection, um Schriften in der gesamten Anwendung zu ändern, ohne TextViews zu erweitern. Schauen Sie sich diesen SO-Beitrag an

UPDATE 2

Beginnend mit API Level 26 und verfügbar in der 'Support Library', die Sie verwenden können

android:fontFamily="@font/embeddedfont"

Weitere Informationen: Schriftarten in XML

Longi
quelle
25
Dies ist nicht die Lösung. Ich verwende viele verschiedene Ansichten, nicht nur die Textansicht. Ich möchte die Schriftart einmal einstellen und vergessen. Außerdem erstellt Ihr Code für jede Textansicht ein neues Objekt. Deklarieren Sie das Feld mindestens als statisch, um die Schriftart einmal aus Assets zu laden.
Tomrozb
2
... nun, es gibt eine Such- und Ersetzungsfunktion, die in diesem Fall sehr gut funktioniert
Longi
1
Das wird nicht funktionieren. Sie können nicht aufrufen, getContext()wenn die Variable statisch ist. Sie sollten es auf Singleton-ähnliche Weise implementieren, da sonst der aktuelle Code nicht einmal kompiliert wird.
Tomrozb
1
Ich habe das letzte Commit zurückgesetzt.
Longi
1
@ Tomrozb: D Ich habe gerade festgestellt, dass die letzten schnellen Änderungen, die ich vorgenommen habe, auf Ihre Kommentare zurückzuführen sind! Wenn Sie genug Punkte haben, können Sie das Codebeispiel gerne selbst optimieren. ansonsten werden wir in ein paar Jahren noch über das Thema sprechen, wenn sich niemand mehr um Smartphones kümmert;)
longi
8

Fügen Sie diese Codezeile in Ihre Datei res / value / styles.xml ein

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

Der gesamte Stil wird so aussehen

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

Ändern Sie "Circular_Medium" in Ihren eigenen Schriftnamen.

Nirazverma
quelle
6

Sprechen Sie nicht über die Leistung. Bei benutzerdefinierten Schriftarten können Sie eine rekursive Methodenschleife durch alle Ansichten erstellen und die Schriftart festlegen, wenn es sich um eine Textansicht handelt:

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

Übergeben Sie in all Ihren Aktivitäten die aktuelle ViewGroup nach setContentView und fertig:

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

Für Fragment können Sie etwas Ähnliches tun.

Allen Chan
quelle
1
Klingt gut, fragt sich aber, wie es in recyclerView-Inhalten funktioniert?
Srujan Barai
Ich habe es gerade versucht. zu schwer zum rendern. Verlangsamung recyclerViewwie die Hölle.
Srujan Barai
Dieser Trick wird für keine Listenansicht empfohlen und dient nur dazu, Zeit zu sparen, um die statische Ansicht zu codieren.
Allen Chan
5

Eine andere Möglichkeit, dies für die gesamte App zu tun, ist die Verwendung der Reflexion basierend auf dieser Antwort

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

Wenn Sie dann die Schriftarten überschreiben möchten, können Sie die Methode einfach aufrufen und ihr eine Karte mit Schriftarten wie folgt geben:

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

für die vollständige Beispiel Scheck

Dies funktioniert nur für Android SDK 21 und höher, für frühere Versionen überprüfen Sie das vollständige Beispiel

Ismail Almetwally
quelle
5

Verwenden Sie einfach diese Bibliothek, kompilieren Sie sie in Ihrer Notendatei

complie'me.anwarshahriar:calligrapher:1.0'

und verwenden Sie es in der onCreate-Methode in der Hauptaktivität

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

Dies ist der eleganteste superschnelle Weg, dies zu tun.

Mohamed Ayed
quelle
2

Dies ist Arbeit für mein Projekt, Quelle https://gist.github.com/artem-zinnatullin/7749076

Erstellen Sie ein Schriftartenverzeichnis im Asset-Ordner und kopieren Sie dann Ihre benutzerdefinierte Schriftart in das Schriftartenverzeichnis. Beispiel: Ich verwende trebuchet.ttf.

Erstellen Sie eine Klasse 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) {

        }
    }
}

Thema in styles.xml bearbeiten unten hinzufügen

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

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

Rufen Sie schließlich in Aktivität oder Fragment onCreate TypefaceUtil.java auf

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

Android bietet nicht viel Unterstützung für das Anwenden von Schriftarten in der gesamten App (siehe dieses Problem ). Sie haben 4 Möglichkeiten, um die Schriftart für die gesamte App festzulegen:

  • Option 1: Wenden Sie Reflection an, um die Systemschriftart zu ändern
  • Option 2: Erstellen und Unterklassen von benutzerdefinierten Ansichtsklassen für jede Ansicht, die eine benutzerdefinierte Schriftart benötigt
  • Option 3: Implementieren Sie einen View Crawler, der die Ansichtshierarchie für den aktuellen Bildschirm durchläuft
  • Option 4: Verwenden Sie eine Bibliothek eines Drittanbieters.

Details zu diesen Optionen finden Sie hier .

Phileo99
quelle
0

Ich weiß, dass diese Frage ziemlich alt ist, aber ich habe eine gute Lösung gefunden. Grundsätzlich übergeben Sie dieser Funktion ein Container-Layout, das die Schriftart auf alle unterstützten Ansichten und rekursiv in untergeordneten Layouts anwendet:

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

lediglich Set Schrift von App normal, sans, serifoder monospace(nicht zu einer benutzerdefinierten Schriftart!), können Sie dies tun.

Definieren Sie ein Thema und legen Sie das android:typefaceAttribut auf die Schriftart fest, in der Sie Folgendes verwenden möchten 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>

Wenden Sie das Thema auf die gesamte App in der AndroidManifest.xmlDatei an:

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

Android Referenz

Eric
quelle
Bist du sicher, dass das funktioniert? Laut Android-Dokument: "Muss einer der folgenden konstanten Werte sein: Normal, Sans, Serif, Monospace".
Tomrozb
1
Oh, ich verstehe ... du hast Recht ... ich habe die Frage doch nicht verstanden: x Ich wollte nur, dass meine gesamte App eine Monospace-Schriftart (nicht benutzerdefiniert) verwendet, und ich habe gesehen, dass sie funktioniert, also habe ich dies gepostet hier ......... ich denke meine Antwort könnte immer noch nützlich sein für andere, die etwas Ähnliches machen wollen .... also werde ich es bearbeiten und hier lassen ..... ich bin in Ordnung, oder? sammelt Stimmen nach unten. Vielen Dank für den Hinweis
Eric
Hey @ Dave Cruise, funktioniert es nur für Monospace? Ich habe es nur für Monospace getestet ... und sonst nichts ... also bin ich mir nicht sicher ... aber laut Dokumentation sollte es auch für "normal", "sans" und "serif" funktionieren. Ich denke, die Schrift ist allgemeiner als die Schrift, daher können wir sie nicht verwenden, um die Schriftart der App auf eine bestimmte Schriftart wie "consolas" oder so einzustellen.
Eric
@ Eric ja. Ich habe auch keine Ahnung. Monospace arbeiten wie ein Zauber, aber kein Glück für Normal, Sans oder Serif.
Dave Cruise
0

Probieren Sie diese Bibliothek aus, sie ist leicht und einfach zu implementieren

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

Die Antwort ist nein, das kannst du nicht. Siehe Ist es möglich, eine benutzerdefinierte Schriftart für die gesamte Anwendung festzulegen? für mehr Informationen.

Es gibt Problemumgehungen, aber nichts in den Zeilen "eine einzige Codezeile hier und alle meine Schriftarten werden dies statt das sein ".

(Ich danke Google und Apple dafür). Benutzerdefinierte Schriftarten haben einen Platz, aber wenn sie leicht App-weit ersetzt werden könnten, hätte dies eine ganze Welt von Comic Sans- Anwendungen geschaffen.

Martin Marconcini
quelle
41
Stimme deinem Kommentar überhaupt nicht zu. Das globale Festlegen einer Schriftart sollte trivial sein und nicht die erforderlichen Problemumgehungen erfordern. Es liegt an den Entwicklern / Designern der Welt, die "Comic Sans" -Anwendungen zu vermeiden, nicht an Google / Apple, um dies durchzusetzen.
LocalPCGuy
4
Konsistenz> Ausgefallenes Design.
Martin Marconcini
14
Konsistenz <Funktionalität. Wir entwickeln Apps, die biblisches Hebräisch anzeigen. Alle Standard-Schriftarten, die auf Android-Geräten zu finden sind (einschließlich der neuesten Android L-Schriftarten), machen einen miserablen Job beim Rendern von Cantillationszeichen (und sie machen einen mittelmäßigen Job bei Vokalzeichen, obwohl sie immer besser werden). Wir müssen unbedingt eine benutzerdefinierte Schriftart in unserer App verwenden, und wir mussten viel zu viel Code schreiben, um alle erforderlichen Ansichten zu erhalten.
Ted Hopp