Jak ustawić domyślną rodzinę czcionek dla całej aplikacji na Androida

282

Używam jasnej czcionki Roboto w mojej aplikacji. Aby ustawić czcionkę, muszę dodać ją android:fontFamily="sans-serif-light"do każdego widoku. Czy istnieje sposób zadeklarowania czcionki Roboto jako domyślnej rodziny czcionek w całej aplikacji? Próbowałem tak, ale to nie działało.

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

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:fontFamily">sans-serif-light</item>
</style>
tomrozb
źródło
2
To może ci pomóc: stackoverflow.com/a/16883281/1329733
Jacob R
2
Możesz teraz określać niestandardowe czcionki bezpośrednio z pliku XML w Android Studio 3.0 developer.android.com/guide/topics/ui/look-and-feel/...
Siedem

Odpowiedzi:

289

Odpowiedź brzmi tak.

Globalne światło Roboto TextViewi Buttonklasy:

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

Po prostu wybierz styl, który chcesz z listy themes.xml , a następnie utwórz własny styl na podstawie oryginalnego. Na koniec zastosuj styl jako motyw aplikacji.

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

Będzie działać tylko z wbudowanymi czcionkami, takimi jak Roboto, ale to było pytanie. W przypadku czcionek niestandardowych (na przykład ładowanych z zasobów) ta metoda nie będzie działać.

EDYCJA 08/13/15

Jeśli używasz motywów AppCompat, pamiętaj o usunięciu android:prefiksu. Na przykład:

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

Uwaga: buttonStylenie zawiera android:przedrostka, ale textViewStylemusi go zawierać.

tomrozb
źródło
4
Skąd masz sans-serif-lightwartość? Czy istnieje fontFamilygdzieś lista prawidłowych wartości ? Przeglądałem dokumenty, a także pliki motywów i stylów w źródle Androida i nic nie mogę znaleźć.
Christopher Perry
34
jest to możliwe tylko dla API poziomu 16 .. nazwa „android: fontFamily” istnieje tylko na poziomie 16 lub wyższym .. czy istnieje sposób, aby to zrobić również na przykład dla API 14?
Lorenzo Barbagli
3
@LorenzoBarbagli, możesz sprawdzić kaligrafię
Brais Gabin
10
Co mam zrobić, jeśli mam niestandardową czcionkę?
Rohit Tigga
2
tak ,, chcę również dodać niestandardową czcionkę do całej aplikacji. Jak mogę to zrobić ?. Czy muszę zastąpić TextView i zastąpić wszystkie TextView, jak sugerowano w pierwszej odpowiedzi
John
144

Wraz z wydaniem Androida Oreo możesz skorzystać z biblioteki wsparcia, aby osiągnąć ten cel.

  1. Sprawdź w swojej aplikacji build.gradle, czy masz bibliotekę wsparcia > = 26.0.0
  2. Dodaj folder „ font ” do folderu zasobów i dodaj tam czcionki
  3. Odwołaj się do domyślnej rodziny czcionek w głównym stylu aplikacji:

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

Sprawdź https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html w celu uzyskania bardziej szczegółowych informacji.

João Magalhães
źródło
9
W przypadku interfejsu API 26+ powinna to być zaakceptowana metoda. Korzystając z Biblioteki pomocy technicznej , wystarczy usunąć android:prefiks
webo80
2
jeśli używasz tylko wersji bez prefiksu, jest w porządku.
Prefiks
2
Nie wszędzie ustawia się czcionkę ... np. Jeśli masz style, które pochodzą Base.TextAppearance.AppCompat, nie jest tam używana.
Ixx,
3
@ Ixx, jak też przesłonić te style?
Primož Kralj
2
Pamiętaj, aby używać także AppCompatTextView podczas celowania w api <26
Codelicious
37

Aby zmienić czcionkę aplikacji, wykonaj następujące czynności:

  1. Wewnątrz reskatalogu utwórz nowy katalog i wywołaj gofont .
  2. Wstaw czcionkę .ttf / .otf do folderu czcionek. Upewnij się, że nazwa czcionki to małe litery i podkreślenie.
  3. Inside res-> values-> styles.xmlinside <resources>-> <style>dodaj swoją czcionkę <item name="android:fontFamily">@font/font_name</item>.

wprowadź opis zdjęcia tutaj

Teraz cały tekst Twojej aplikacji powinien znajdować się w dodawanej fontannie.

chłopak
źródło
8
korzystając z czcionek niestandardowych, jak dodać pogrubioną czcionkę i zwykłe czcionki?
Rajbir Shienh
Działa to tylko z API poziomu 26 i wyższym, co z API 21 i niższymi?
zulkarnain shah
34

PRZECZYTAJ PONIŻSZE AKTUALIZACJE

Miałem ten sam problem z osadzaniem nowej czcionki i wreszcie zacząłem pracować z rozszerzeniem TextView i ustawić czcionkę wewnątrz.

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

Musisz zmienić TextView Elements później z na w każdym elemencie. A jeśli używasz Kreatora interfejsu użytkownika w środowisku Eclipse, czasami nie wyświetla poprawnie TextViews. To była jedyna rzecz, która działa dla mnie ...

AKTUALIZACJA

Obecnie używam refleksji, aby zmieniać kroje w całej aplikacji bez rozszerzania TextView. Sprawdź ten post SO

AKTUALIZACJA 2

Począwszy od interfejsu API na poziomie 26 i dostępnego w „bibliotece pomocy”, której można użyć

android:fontFamily="@font/embeddedfont"

Dalsze informacje: Czcionki w XML

longi
źródło
25
To nie jest rozwiązanie. Używam wielu różnych widoków, nie tylko TextView. Chcę raz ustawić czcionkę i zapomnieć o tym. Ponadto Twój kod tworzy nowy obiekt dla każdego TextView. Przynajmniej zadeklaruj pole jako statyczne, aby raz załadować czcionkę z zasobów.
tomrozb
2
... no cóż, jest funkcja znajdowania i zamiany, która w tym przypadku działa naprawdę dobrze
longi
1
To nie zadziała. Nie można wywoływać, getContext()gdy zmienna jest statyczna. Powinieneś wdrożyć go w sposób singleton, w przeciwnym razie obecny kod nawet się nie skompiluje.
tomrozb
1
cofnąłem ostatnie zatwierdzenie.
longi
1
@tomrozb: D Właśnie zdałem sobie sprawę, że ostatnie szybkie zmiany, które zrobiłem, były spowodowane Twoimi komentarzami! ponieważ masz wystarczającą liczbę punktów, możesz samodzielnie zoptymalizować przykładowy kod. w przeciwnym razie nadal będziemy rozmawiać na ten temat za kilka lat, kiedy już nikt nie będzie dbał o smartfony;)
longi
8

Dodaj ten wiersz kodu do pliku res / value / styles.xml

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

tak będzie wyglądał cały styl

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

zmień „circular_medium” na własną nazwę czcionki.

nirazverma
źródło
6

Nie mów o wydajności, dla niestandardowej czcionki możesz mieć pętlę metody rekurencyjnej przez wszystkie widoki i ustawić krój pisma, jeśli jest to 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");
    }
}

W całej swojej aktywności przekaż do niej bieżącą grupę ViewGroup po ustawieniu setContentView i gotowe:

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

Dla fragmentu możesz zrobić coś podobnego.

Allen Chan
źródło
1
Brzmi świetnie, ale zastanawiasz się, jak sprawić, by działał w recyklerze Wyświetl zawartość?
Srujan Barai,
Właśnie tego spróbowałem. za ciężki do renderowania. Zwalniam recyclerViewjak diabli.
Srujan Barai
Zupełnie nie jest to zalecane w przypadku żadnego widoku listy, ta sztuczka służy jedynie do oszczędzania czasu na kodowanie widoku statycznego.
Allen Chan,
5

Innym sposobem na zrobienie tego dla całej aplikacji jest użycie refleksji opartej na tej odpowiedzi

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

wtedy za każdym razem, gdy chcesz zastąpić czcionki, możesz po prostu wywołać metodę i dać jej mapę czcionek w następujący sposób:

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

dla pełnego sprawdzenia przykładu

Działa to tylko w przypadku zestawu Android SDK 21 i nowszych wersji we wcześniejszych wersjach. Sprawdź pełny przykład

Ismail Almetwally
źródło
5

Po prostu użyj tej biblioteki, skompiluj ją w pliku ocen

complie'me.anwarshahriar:calligrapher:1.0'

i użyj go w metodzie onCreate w głównej działalności

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

To najbardziej elegancki i szybki sposób na zrobienie tego.

Mohamed Ayed
źródło
2

To jest praca dla mojego projektu, źródło https://gist.github.com/artem-zinnatullin/7749076

Utwórz katalog czcionek w folderze zasobów, a następnie skopiuj własną czcionkę do katalogu czcionek, na przykład używam trebuchet.ttf;

Utwórz klasę 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) {

        }
    }
}

Edytuj motyw w styles.xml dodaj poniżej

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

Przykład w 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>

Wreszcie w działaniu lub fragmencie onCreate wywołaj TypefaceUtil.java

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

Android nie zapewnia wsparcia dla stosowania czcionek w całej aplikacji (zobacz ten problem) ). Masz 4 opcje ustawienia czcionki dla całej aplikacji:

  • Opcja 1: Zastosuj odbicie, aby zmienić czcionkę systemową
  • Opcja 2: Utwórz i podklasuj niestandardowe klasy widoku dla każdego widoku, który wymaga niestandardowej czcionki
  • Opcja 3: Zaimplementuj przeszukiwacz widoków, który przegląda hierarchię widoków dla bieżącego ekranu
  • Opcja 4: Użyj biblioteki innej firmy.

Szczegóły tych opcji można znaleźć tutaj .

Phileo99
źródło
0

Wiem, że to pytanie jest dość stare, ale znalazłem dobre rozwiązanie. Zasadniczo przekazujesz układ kontenera do tej funkcji, która zastosuje czcionkę do wszystkich obsługiwanych widoków i rekurencyjnie cicle w układach potomnych:

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
źródło
0

jedynie do zadanej czcionki z app normal, sans, seriflub monospace(nie niestandardową czcionkę!), można to zrobić.

zdefiniuj motyw i ustaw android:typefaceatrybut na krój pisma, którego chcesz używać 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>

zastosuj motyw do całej aplikacji w AndroidManifest.xmlpliku:

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

referencje Androida

Eric
źródło
Jesteś pewien, że to działa? Według dokumentu Androida: „Musi być jedną z następujących stałych wartości: normal, sans, serif, monospace”.
tomrozb
1
Och, rozumiem ... masz rację ... w końcu nie rozumiem pytania: x Chciałem tylko, aby cała moja aplikacja używała czcionki o stałej szerokości (nie niestandardowej) i zobaczyłem, że działa, więc opublikowałem to tutaj ......... myślę, że moja odpowiedź może być nadal przydatna dla innych, którzy chcą zrobić coś podobnego .... więc zredaguję to i zostawię tutaj ..... nic mi nie jest, prawda? kumuluje się głosy. dzięki za zwrócenie na to uwagi
Eric,
Hej @Dave Cruise, czy to działa tylko w przestrzeni kosmicznej? Testowałem go tylko pod kątem monospace ... i nic więcej ... więc nie jestem pewien ... ale zgodnie z dokumentacją powinien on również działać dla "normal", "sans" i "serif" .. . myślę, że krój pisma jest bardziej ogólny niż czcionka, więc nie możemy go użyć do ustawienia czcionki aplikacji na określoną czcionkę, np. „konsole” lub coś w tym rodzaju.
Eric
@Eric tak. też nie mam pojęcia. monospace działają jak urok, ale nie mają szczęścia dla normalnych, bezszeryfowych i szeryfowych.
Dave Cruise
0

Wypróbuj tę bibliotekę, lekką i łatwą do wdrożenia

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
źródło
-7

Odpowiedź brzmi: nie, nie możesz. Zobacz Czy można ustawić niestandardową czcionkę dla całej aplikacji? po więcej informacji.

Istnieją obejścia, ale nic w wierszach „jednego wiersza kodu tutaj i wszystkie moje czcionki będą takie zamiast tego ”.

(W pewnym sensie dziękuję za to Google i Apple). Niestandardowe czcionki mają swoje miejsce, ale dzięki czemu można je łatwo zastąpić szeroką aplikacją, stworzyłby cały świat aplikacji Comic Sans )

Martin Marconcini
źródło
41
Całkowicie nie zgadzam się z twoim komentarzem. Globalne ustawienie czcionki powinno być trywialne, a nie wymagałoby tego rodzaju obejść. Wymuszenie przez twórców / projektantów na całym świecie unikania aplikacji „Comic Sans”, a nie Google / Apple.
LocalPCGuy
4
Spójność> Fantazyjny design.
Martin Marconcini,
14
Jednak spójność <funkcjonalność. Tworzymy aplikacje, które wyświetlają biblijny hebrajski. Wszystkie standardowe czcionki znalezione na urządzeniach z Androidem (w tym najnowsze czcionki L z Androidem) wykonują fatalną robotę renderowania znaków cantillation (i w tym przypadku wykonują mierną pracę na znakach samogłoskowych, chociaż są coraz lepsze). Absolutnie musimy użyć niestandardowej czcionki w całej naszej aplikacji i musieliśmy napisać o wiele za dużo kodu, aby uzyskać wszystkie wymagane widoki.
Ted Hopp