Jak ustawić niestandardową czcionkę dla całej aplikacji w systemie Android?

83

Czy można ustawić niestandardową czcionkę w aplikacji na Androida?

Wypróbowałem to, co jest tutaj opublikowane , ale nie wiem, gdzie jest moja extends Applicationklasa ...

Jakaś pomoc?

EDYTOWAĆ:

Wypróbowałem następujące:

  • Dodaj folder zasobów i wstaw czcionkę do środka, jak pokazano tutaj:

wprowadź opis obrazu tutaj

  • Dodaj nową klasę, która pochodzi od Application

  • Zadzwoń do tej nowej klasy z mojego AndroidManifest.xml.

  • Poszedłem do swojego stylu i dodałem go.

MyApp.java:

public class MyApp extends Application {
  @Override
  public void onCreate() {
     super.onCreate();
    FontsOverride.setDefaultFont(this, "DEFAULT", "raleway_regular.ttf");
    //  This FontsOverride comes from the example I posted above
  }
  }

AndroidManifest.xml:

<application
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:supportsRtl="true"
      android:name=".MyApp"
      android:theme="@style/AppTheme">
     ....

styles.xml:

 <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:fontFamily">default</item>
 </style>

Ale moja czcionka nadal się nie zmienia ... Masz jakiś pomysł?

Następnie MyAppwywoływana jest klasa. Ale bez wpływu na moje czcionki ...

EDIT2: Zdałem sobie sprawę, że moje przyciski stosują niestandardową czcionkę po ustawieniu niestandardowego stylu dla moich przycisków. Oto mój niestandardowy styl przycisku:

<style name="MyButtonStyle" parent="Widget.AppCompat.Button">
    <item name="textAllCaps">false</item>
    <item name="android:textAllCaps">false</item>
</style>

A oto jak to wygląda teraz:

wprowadź opis obrazu tutaj

Więc: mój przycisk stosuje styl, ale nie TextView. Masz jakiś pomysł, dlaczego moja niestandardowa czcionka nie jest stosowana do wszystkich elementów w aplikacji?

Sonhja
źródło
link, który podałeś, jest naprawdę pomocny w rozwiązaniu problemu.
Androider,
Wiem, myślę, że moje rozwiązanie jest tam ... Ale kiedy tworzę klasę, która rozszerza się z Application, nie mogę sprawić, by działała, ponieważ mówi, że moja klasa nigdy nie jest używana ...
Sonhja,
kasy jeszcze kilka linków w mojej odpowiedzi, wydaje się być pomocny, jeszcze jedno mój pierwszy link jest naprawdę lepiej, Dzięki
Androider

Odpowiedzi:

50

Napisz zajęcia

public class MyApp extends Application{
// Put the onCreate code as you obtained from the post link you reffered
}

teraz następną rzeczą jest w AndroidManifest.xml dla tagu aplikacji podaj nazwę swojej klasy aplikacji. W tym przypadku jest to MyApp

<application
android:name=".MyApp"
...
>
...
</application>

Dlatego przy każdym otwarciu aplikacji wywoływana byłaby metoda onCreate klasy MyApp i ustawiana byłaby czcionka.

Zaktualizuj Umieść plik czcionki w obszarze asset / fonts / your_font_file.ttf

Umieść tę linię w metodzie onCreate swojej klasy aplikacji (MyApp)

TypefaceUtil.overrideFont(getApplicationContext(), "SERIF", "fonts/your_font_file.ttf");

Plik źródłowy dla TypefaceUtil

public class TypefaceUtil {

    /**
     * Using reflection to override default typeface
     * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE OVERRIDDEN
     *
     * @param context                    to work with assets
     * @param defaultFontNameToOverride  for example "monospace"
     * @param customFontFileNameInAssets file name of the font from assets
     */
    public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) {

        final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Map<String, Typeface> newMap = new HashMap<String, Typeface>();
            newMap.put("serif", customFontTypeface);
            try {
                final Field staticField = Typeface.class
                        .getDeclaredField("sSystemFontMap");
                staticField.setAccessible(true);
                staticField.set(null, newMap);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        } else {
            try {
                final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);
                defaultFontTypefaceField.setAccessible(true);
                defaultFontTypefaceField.set(null, customFontTypeface);
            } catch (Exception e) {
                Log.e(TypefaceUtil.class.getSimpleName(), "Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride);
            }
        }
    }
}

Teraz zaktualizuj plik style.xml

umieść poniższą linię swojego stylu, który jest zawarty w Twojej działalności w pliku manifestu

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

Mam nadzieję że to pomoże

Nitin Mesta
źródło
Daj mi znać swoją wersję systemu operacyjnego Android, na którym testujesz. Zauważyłem, że w Lollipopie musimy zrobić więcej tweeksów
Nitin Mesta
Proszę sprawdzić poniższy link, aby znaleźć rozwiązanie dla Lollipopa i poprzednich wersji Androida: ( stackoverflow.com/a/36206275/2268466 )
blueware
zmienia całą czcionkę aplikacji w wyskakującej wiadomości, oknie ostrzeżenia, nie chcę w tym
używać
1
Mam wątpliwości, wielu producentów zezwala użytkownikowi na zmianę czcionek w całym systemie z poziomu ustawień, czy ta zmiana również zastępuje nasz typ czcionki, który ustawiliśmy programowo?
Bhuro
A co z ustawieniem wielu czcionek?
Gaurav Mandlik
82

EDYTOWAĆ

uk.co.chrisjenx:calligraphyLib nie jest bardziej konserwowany, ponieważ alternatywa dla najnowszej wersji Androida jest teraz https://github.com/InflationX/Calligraphy

dependencies {
    implementation 'io.github.inflationx:calligraphy3:3.1.1'
    implementation 'io.github.inflationx:viewpump:2.0.3'
}

Dodaj własne czcionki do zasobów /

Stosowanie

Dla domyślnej czcionki

Zdefiniuj domyślną czcionkę za pomocą CalligraphyConfig w swojej klasie Application w metodzie #onCreate () i przekaż ją do CalligraphyInterceptor, którą dodajesz do konstruktora ViewPump.

@Override
public void onCreate() {
    super.onCreate();
    ViewPump.init(ViewPump.builder()
        .addInterceptor(new CalligraphyInterceptor(
                new CalligraphyConfig.Builder()
                    .setDefaultFontPath("fonts/Roboto-RobotoRegular.ttf")
                    .setFontAttrId(R.attr.fontPath)
                    .build()))
        .build());
    //....
}

Wstrzyknij w kontekst: zawiń kontekst działania:

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase));
}

Styl niestandardowy

<style name="TextViewCustomFont">
    <item name="fontPath">fonts/RobotoCondensed-Regular.ttf</item>
</style>

Motyw

<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
    <item name="android:textViewStyle">@style/AppTheme.Widget.TextView</item>
</style>

<style name="AppTheme.Widget"/>

<style name="AppTheme.Widget.TextView" parent="android:Widget.Holo.Light.TextView">
    <item name="fontPath">fonts/Roboto-ThinItalic.ttf</item>
</style>

Nie jest bardziej utrzymywany przez deweloperów poniżej rozwiązania


W systemie Android jest wspaniała biblioteka niestandardowych czcionek: Kaligrafia
Oto przykład, jak z niej korzystać.

W Gradle musisz umieścić ten wiersz w pliku build.gradle swojej aplikacji:

        dependencies {
            compile 'uk.co.chrisjenx:calligraphy:2.2.0'
        }

Następnie utwórz klasę rozszerzającą Application i napisz ten kod:

        public class App extends Application {
            @Override
            public void onCreate() {
                super.onCreate();

                CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
                                .setDefaultFontPath("your font path")
                                .setFontAttrId(R.attr.fontPath)
                                .build()
                );
            }
        } 

Powinieneś zrobić na asset / a "New Directory" "fonts" (patrz poniżej), więc w tym kodzie "twoja ścieżka do czcionki" powinna mieć postać "fonts / SourceSansPro-Regular.ttf". (To tylko „czcionki…”, a nie „/ fonts ..” lub „zasoby…”)

A w klasie activity umieść tę metodę przed onCreate:

        @Override
        protected void attachBaseContext(Context newBase) {
            super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
        }

I ostatnia rzecz, którą twój plik manifestu powinien wyglądać tak:

        <application
           .
           .
           .
           android:name=".App">

I zmieni całą aktywność na Twoją czcionkę! to proste i czyste!

Na Zasobach kliknij prawym przyciskiem myszy Nowy katalog, nazwij go „czcionkami”. W wyszukiwarce umieść tam .ttfpliki czcionek.

wprowadź opis obrazu tutaj

Nie zapomnij również dodać poniżej dwóch wierszy w attrs.xml, jeśli nie masz pliku attrs.xml, utwórz nowy plik w values.xml

 <attr format="string" name="fontPath"/> 
    <item name="calligraphy_tag_id" type="id"/>
Rajesh Nasit
źródło
Używam ttf, ale jestem prawie pewien, że .otf również będzie działać i najlepsza lokalizacja, aby umieścić go w folderze zasobów.
Rajesh Nasit
Umieść to w rozszerzeniu Klasa aplikacji CalligraphyConfig.initDefault (new CalligraphyConfig.Builder () .setDefaultFontPath ("fonts / GOTHAM-MEDIUM.ttf") .setFontAttrId (R.attr.fontPath) .build ()); Nie zapomnij też dodać poniżej dwóch wierszy w values.xml <attr format = "string" name = "fontPath" /> <item name = "calligraphy_tag_id" type = "id" />
Rajesh Nasit
cześć @rajesh! powinieneś kliknąć „Edytuj” i dodać to do swojej świetnej odpowiedzi! masz rację, powinny to być pliki .ttf , przepraszam.
Fattie
1
Możesz użyć fragmentu maksymalnie. Więc ta liczba działań zostanie zmniejszona.
Rajesh Nasit
1
@Pawan zrobić jeden krok - zdefiniować prostą klasę bazową gdzie attachBaseContext(..)jest realizowany, a następnie wszystkie moje zajęcia z realizacji projektu (gdzie chcę tego niestandardowej czcionki) rozszerzenie tej klasy podstawowej
Gene Bo
65

Wszystko co zrobiłem to:

1: Dodano „nowy katalog zasobów” do folderu RES, Wybrano TYP ZASOBU jako „czcionkę” z podanej listy rozwijanej, nazwano nowy katalog „czcionką” i zapisano. NOWY KATALOG ZASOBÓW

2: Dodano mój „custom_font.ttf” do właśnie utworzonego folderu FONT.

3: Dodano moją niestandardową czcionkę do motywu podstawowego aplikacji w STYLES.XML

STYLES.XML

GOTOWE.

Numanqmr
źródło
4
Musisz także utworzyć rodzinę czcionek. Potem zadziałało dla mnie. Szczegóły tutaj: developer.android.com/guide/topics/ui/look-and-feel/…
keybee
zadziałało dla mnie bez konieczności tworzenia rodziny czcionek. Jednak musiałem użyć wersji Gradle> 3 i zbudować narzędzia oraz obsługiwać biblioteki ustawione na 27> @keybee
Numanqmr
Działało świetnie, nawet bez rodziny czcionek
Julian Alberto
czy wiesz, jak zmienić to programowo?
majov
@majov sprawdź powyższą odpowiedź przez #Rajeesh. to powinno ci pomóc!
Numanqmr
12

Możesz to zrobić za pomocą Android SDK teraz, jako oficjalny kanał YouTube Developer dla Androida opublikowany w zestawie / 2017 tutaj .

Wymaga poziomu interfejsu API 26 (Android 8 Oreo) lub nowszego.

Wystarczy umieścić plik czcionki w res/fontfolderze i odwołać się do niego TextViewna wypadek, gdybyś potrzebował konkretnego z android:fontFamilyatrybutem.

Jeśli chcesz mieć podstawową czcionkę w całej aplikacji, po prostu umieść

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

w Twoim styles.xml

Jeśli chcesz, możesz pobrać niestandardową czcionkę z Android Studio i w podróży. Wszystko to można znaleźć wraz ze szczegółami na powyższym filmie.

Francisco Nin
źródło
Ta opcja dotyczy interfejsu API 26 i nowszych. Not 16+
Perfect Square
co powiesz na naprawę API 23 +?
Raju yourPepe
12

Android zapewnia prostsze i najlepsze rozwiązania, które są obsługiwane na poziomie API 14 przez Support Library 26+. Czcionki w XML Obsługuje również opcję rodziny czcionek . Wymagany import: implementation "com.android.support:support-compat:<26+ version>"

Wykonaj te proste czynności, a rodzina czcionek zostanie zastosowana w Twojej aplikacji bez żadnych przeszkód:

  1. Utwórz katalog czcionek wewnątrz res
  2. Wklej plik czcionek do czcionki
  3. Kliknij prawym przyciskiem myszy folder czcionek i przejdź do Nowy> Plik zasobów czcionek. Zostanie wyświetlone okno New Resource File.
  4. Dodaj następujące atrybuty
<?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>
  1. W powyższym pliku xml. Używaj aplikacji tylko do korzystania z biblioteki pomocy. W przeciwnym razie możesz użyć Androida, jeśli Twoja aplikacja jest przeznaczona dla interfejsu API na poziomie 26+.
  2. Teraz przejdź do swojego styles.xml i umieść poniżej linię swojego głównego stylu.
    <item name="android:fontFamily">@font/opensans</item>
    
  3. Ważne: używaj AppCompatActivity tylko wtedy, gdy używasz biblioteki obsługi.
  4. Lub użyj poniżej, aby programowo ustawić krój pisma

    view.setTypeface(ResourcesCompat.getFont(context, R.font.opensans));
    
Kuldeep Sakhiya
źródło
W ten sposób nadaje się do aktualnej funkcji zasobów czcionek systemu Android. Dzięki.
azwar_akbar
2

Wygląda na to, że używasz android:fontFamilyzamiast android:typefacew swoim styles.xml.

Spróbuj wymienić

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:fontFamily">default</item>
</style>

z

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:typeface">default</item>
</style>
Suhas
źródło
1
Jak mam to połączyć z moją aplikacją? Kto od tego rozciąga?
Sonhja
Cóż, rozszerzając Application, po prostu tworzysz podklasę klasy swojej aplikacji Application. Więc nie musisz go podłączać.
Suhas
Co mówi, że nigdy nie jest używane?
Suhas
Czy dodałeś również <item name="android:typeface">default</item>linię <style name="AppTheme" parent="AppBaseTheme">w res -> values -> styles.xmlpliku swojej aplikacji, zgodnie z sugestią w tym samym poście SO?
Suhas
Tak, i to też nie działa. Właśnie to umieściłem w mojej edycji ... :(
Sonhja,
2

Jeśli zastosujesz się do pierwszego tematu, powinno to zadziałać: Tutaj

Tak, z refleksją. To działa ( na podstawie tej odpowiedzi ):

(Uwaga: jest to obejście z powodu braku obsługi niestandardowych czcionek, więc jeśli chcesz zmienić tę sytuację, zrób gwiazdkę, aby zagłosować tutaj na problem z Androidem). Uwaga: nie zostawiaj komentarzy „ja też” na ten temat, każdy, kto go obejrzał, otrzyma e-maila, gdy to zrobisz. Więc po prostu „gwiazdkuj”, proszę.

import java.lang.reflect.Field;
import android.content.Context;
import android.graphics.Typeface;

public final class FontsOverride {

public static void setDefaultFont(Context context,
        String staticTypefaceFieldName, String fontAssetName) {
    final Typeface regular = Typeface.createFromAsset(context.getAssets(),
            fontAssetName);
    replaceFont(staticTypefaceFieldName, regular);
}

protected static void replaceFont(String staticTypefaceFieldName,
        final Typeface newTypeface) {
    try {
        final Field staticField = Typeface.class
                .getDeclaredField(staticTypefaceFieldName);
        staticField.setAccessible(true);
        staticField.set(null, newTypeface);
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}
}

Następnie musisz przeładować kilka domyślnych czcionek, na przykład w klasie aplikacji:

public final class Application extends android.app.Application {
    @Override
    public void onCreate() {
        super.onCreate();
        FontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf");
        FontsOverride.setDefaultFont(this, "MONOSPACE", "MyFontAsset2.ttf");
        FontsOverride.setDefaultFont(this, "SERIF", "MyFontAsset3.ttf");
        FontsOverride.setDefaultFont(this, "SANS_SERIF", "MyFontAsset4.ttf");
    }
}

Lub oczywiście, jeśli używasz tego samego pliku czcionki, możesz to poprawić, aby załadować go tylko raz.

Jednak staram się po prostu zastąpić jeden z nich, powiedzieć „MONOSPACE”, a następnie ustawić styl, aby wymusić szeroki zakres kroju czcionki:

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

    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <item name="android:typeface">monospace</item>
    </style>
</resources>

API 21 Android 5.0

Zbadałem raporty w komentarzach, że to nie działa i wydaje się być niezgodne z motywem android: Theme.Material.Light.

Jeśli ten motyw nie jest dla Ciebie ważny, użyj starszego motywu, np .:

<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
    <item name="android:typeface">monospace</item>
</style>
Robin Delaporte
źródło
2
  1. Na początku, należy kliknąć prawym przyciskiem myszy zasobów projektowych, której nazwa resnastępnie z newopcją wyboru Android Resource Directoryi wybierz fontformularz Resource typei naciśnij OK, to stworzy katalog czcionek do umieszczania w nim czcionek.

wprowadź opis obrazu tutaj

  1. Umieść .ttftam pliki czcionek.

wprowadź opis obrazu tutaj

  1. Przejdź do pliku stylu projektu, który istnieje w następującej ścieżce res/values/styles.xml i dodaj takie style:

    <style name="SansSerifFont">
        <item name="android:fontFamily">sans-serif</item>
    </style>
    
    <style name="OpenSansFont">
        <item name="android:fontFamily">@font/open_sans</item>
    </style>
    
    <style name="IranianSansFont">
        <item name="android:fontFamily">@font/iranian_sans</item>
    </style>
    
    <style name="BYekanFont">
        <item name="android:fontFamily">@font/b_yekan</item>
    </style>
    
    <style name="DroidArabicFont">
        <item name="android:fontFamily">@font/droid_arabic</item>
    </style>
    
  2. Przejdź do swojego kodu i napisz taką klasę, aby zmienić czcionkę całej aplikacji:

    public class AppFontManager {
    
        private AppCompatActivity appCompatActivity;
    
        public static final String SANS_SERIF_APP_FONT = "sans_serif";
        public static final String B_YEKAN_APP_FONT = "b_yekan";
        public static final String DROID_ARABIC_APP_FONT = "droid_arabic";
        public static final String IRANIAN_SANS_APP_FONT = "iranian_sans";
        public static final String OPEN_SANS_APP_FONT = "open_sans";
    
        public AppAppearanceManager(AppCompatActivity appCompatActivity) {
            this.appCompatActivity = appCompatActivity;
        }
    
        public void setFont(String fontName){
    
            switch (fontName){
    
                case SANS_SERIF_APP_FONT:{
                    appCompatActivity.getTheme().applyStyle(R.style.SansSerifFont, true);
                    break;
                }
    
                case B_YEKAN_APP_FONT:{
                    appCompatActivity.getTheme().applyStyle(R.style.BYekanFont, true);
                    break;
                }
    
                case DROID_ARABIC_APP_FONT:{
                    appCompatActivity.getTheme().applyStyle(R.style.DroidArabicFont, true);
                    break;
                }
    
                case IRANIAN_SANS_APP_FONT:{
                appCompatActivity.getTheme().applyStyle(R.style.IranianSansFont, true);
                    break;
                }
    
                case OPEN_SANS_APP_FONT:{
                    appCompatActivity.getTheme().applyStyle(R.style.OpenSansFont, true);
                    break;
                }
            }
        }
    }
    

    Ponieważ czcionki powinny być ustawione osobno dla każdej czynności, wolę napisać dla niej klasę, aby kod był bardziej przejrzysty.

  3. Następnie wywołaj metodę klasy przed aktywnością onCreate super.onCreate(savedInstanceState):

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        new AppAppearanceManager(this).setFont(APP_DEFAULT_FONT);
        super.onCreate(savedInstanceState);
    // Do you stuff there...
    }
    

    Pamiętaj, że jeśli chcesz zmienić czcionkę w trakcie działania , napisz wybraną czcionkę w SharedPreferenceslub itp., A następnie przekaż wybraną czcionkę do wszystkich czynności setFontjak powyżej.

Mohsen Pakzad
źródło
1

Utwórz folder zasobów w folderze głównym. Dodaj folder czcionek w nim. dodaj swój plik .ttf w folderze czcionek.

Dodaj następujące elementy do motywu aplikacji:

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

Utwórz klasę jako TypefaceUtil

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

import java.lang.reflect.Field;

public class TypefaceUtil {

    /**
     * Using reflection to override default typeface
     * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE OVERRIDDEN
     * @param context to work with assets
     * @param defaultFontNameToOverride for example "monospace"
     * @param customFontFileNameInAssets file name of the font from assets
     */
    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) {
            Log.e("Can not set","Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride);
        }
    }
}

Wywołaj to w klasie aplikacji lub w działaniu Launchera

        TypefaceUtil.overrideFont(getApplicationContext(), "fonts/roboto_regular.ttf", "fonts/roboto_regular.ttf"); // font from assets: "assets/fonts/Roboto-Regular.ttf
Pratibha Sarode
źródło
0

Najpierw utwórz nową klasę, która zastępuje widok, który chcesz dostosować. (np. chcesz mieć przycisk z niestandardowym krojem czcionki? Rozszerz Button). Na przykład:

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

Teraz, jeśli go nie masz, dodaj dokument XML pod res/values/attrs.xmli dodaj:

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

Okej, więc pomijając to, wróćmy do parseAttributes()metody z wcześniejszej:

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

Teraz wszystko gotowe. Możesz dodać więcej atrybutów do wszystkiego (możesz dodać kolejny dla stylu kroju - pogrubienie, kursywa, itp.), Ale teraz zobaczmy, jak go użyć:

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

xmlns:customLinia może być naprawdę coś, ale konwencja jest co pokazano powyżej. Liczy się to, że jest unikalny i dlatego używana jest nazwa pakietu. Teraz wystarczy użyć custom:przedrostka dla swoich atrybutów i android:przedrostka dla atrybutów Androida.

Ostatnia sprawa: jeśli chcesz to wykorzystać w stylu ( res/values/styles.xml), należy nie dodać xmlns:customlinię. Po prostu odwołaj się do nazwy atrybutu bez przedrostka:

<style name="MyStyle>
    <item name="typeface">roboto</item>
</style>
Archit Goel
źródło
0

Próbowałem też nadpisywania czcionek, ale ostatecznie nie jest to niezawodne rozwiązanie, niestety zastępowanie czcionek wymaga więcej. Możesz poczekać, aż pojawi się Android O z niestandardową czcionką lub skorzystać z biblioteki innej firmy.

Ostatnim rozwiązaniem, na które się natknąłem, była ta biblioteka Caligraphy , która była łatwa do zainicjowania i pozwalała używać dowolnej liczby czcionek. Sprawdzając jego kod źródłowy, zrozumiałem, dlaczego samo zastępowanie czcionek nie zadziała, więc nawet jeśli nie planujesz go używać, polecam przeczytanie go raz.

Powodzenia

Keivan Esbati
źródło
Tak… może. W każdym razie daj nam znać, jeśli znalazłeś przyczynę tego problemu, naprawdę by to docenił. Nie mogłem znaleźć rozwiązania, nawet czytając podstawowe kody.
Keivan Esbati
0

Wypróbuj poniższy kod, działa dla mnie, mam nadzieję, że ci też pomoże.

public class BaseActivity extends AppCompatActivity {

private Typeface typeace;
@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    typeace = Typeface.createFromAsset(getAssets(), getResources().getString(R.string.font_name));
}

@Override
protected void onStart() {
    // TODO Auto-generated method stub
    super.onStart();
    overrideFonts(this,getWindow().getDecorView());
}

private void overrideFonts(final Context context, final View v) {
    try {
        if (v instanceof ViewGroup) {
            ViewGroup vg = (ViewGroup) v;
            for (int i = 0; i < vg.getChildCount(); i++) {
                View child = vg.getChildAt(i);
                overrideFonts(context, child);
         }
        } else if (v instanceof TextView) {
            ((TextView) v).setTypeface(typeace);
        } else if (v instanceof EditText ) {
            ((EditText) v).setTypeface(typeace);
        } else if (v instanceof Button) {
            ((Button) v).setTypeface(typeace);
        }
    } catch (Exception e) {
 }
 }
}

Teraz rozszerz tę BaseActivity na dowolne działanie lub możesz utworzyć tę samą klasę dla fragmentu, jeśli używasz.

Uwaga: - Jeśli chcesz ustawić niektóre z widoków na inny krój, musisz ustawić to programowo, jak poniżej

private Typeface typeface;
typeface = Typeface.createFromAsset(getAssets(), getResources().getString(R.string.font_name_bold));
tvUserName.setTypeface(typeface);

Więc spróbuj i daj mi znać, czy mógłbym ci dalej pomóc

Bhavnik
źródło
0

Będzie to obejście dla kotlina

Streszczenie rozwiązania https://gist.github.com/Johnyoat/040ca5224071d01b3f3dfc6cd4d026f7

Krok pierwszy

Umieść plik czcionki w asset / fonts / your_font_file.ttf i utwórz klasę kotlin o nazwie TypeFaceUtil

   class TypefaceUtil{

    fun overridefonts(context: Context, defaultFontToOverride:String, customFontFileNameInAssets:String){
        try {
            val customTypeface = Typeface.createFromAsset(context.assets,customFontFileNameInAssets)
            val defaultTypefaceField = Typeface::class.java.getDeclaredField(defaultFontToOverride)
            defaultTypefaceField.isAccessible = true
            defaultTypefaceField.set(null,customTypeface)
        }catch (e:Exception){
            Timber.e("Cannot set font $customFontFileNameInAssets instead of $defaultFontToOverride")
        }
    }
}

Krok drugi Następnie w twoimonCreate

val typefaceUtil = TypefaceUtil()

typefaceUtil.overridefonts(this,"SERIF","fonts/font_file.ttf")

Krok trzeci

dodaj to do swojego stylu

<item name="android:typeface">serif</item>
Johnyoat
źródło
0

Nazwy czcionek należy pisać małymi literami, aby były widoczne w aplikacji i pracy.

Mazhar Ali
źródło