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 Application
klasa ...
Jakaś pomoc?
EDYTOWAĆ:
Wypróbowałem następujące:
- Dodaj folder zasobów i wstaw czcionkę do środka, jak pokazano 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 MyApp
wywoł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:
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?
źródło
Odpowiedzi:
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
źródło
EDYTOWAĆ
uk.co.chrisjenx:calligraphy
Lib nie jest bardziej konserwowany, ponieważ alternatywa dla najnowszej wersji Androida jest teraz https://github.com/InflationX/Calligraphydependencies { 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
.ttf
pliki czcionek.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"/>
źródło
attachBaseContext(..)
jest realizowany, a następnie wszystkie moje zajęcia z realizacji projektu (gdzie chcę tego niestandardowej czcionki) rozszerzenie tej klasy podstawowejWszystko 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.
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
GOTOWE.
źródło
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/font
folderze i odwołać się do niegoTextView
na wypadek, gdybyś potrzebował konkretnego zandroid:fontFamily
atrybutem.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.
źródło
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:
Lub użyj poniżej, aby programowo ustawić krój pisma
view.setTypeface(ResourcesCompat.getFont(context, R.font.opensans));
źródło
Wygląda na to, że używasz
android:fontFamily
zamiastandroid:typeface
w swoimstyles.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>
źródło
Application
, po prostu tworzysz podklasę klasy swojej aplikacjiApplication
. Więc nie musisz go podłączać.<item name="android:typeface">default</item>
linię<style name="AppTheme" parent="AppBaseTheme">
wres -> values -> styles.xml
pliku swojej aplikacji, zgodnie z sugestią w tym samym poście SO?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>
źródło
res
następnie znew
opcją wyboruAndroid Resource Directory
i wybierzfont
formularzResource type
i naciśnij OK, to stworzy katalog czcionek do umieszczania w nim czcionek..ttf
tam pliki czcionek.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>
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.
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
SharedPreferences
lub itp., A następnie przekaż wybraną czcionkę do wszystkich czynnościsetFont
jak powyżej.źródło
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
źródło
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.xml
i 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:custom
Linia 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 iandroid:
przedrostka dla atrybutów Androida.Ostatnia sprawa: jeśli chcesz to wykorzystać w stylu (
res/values/styles.xml
), należy nie dodaćxmlns:custom
linię. Po prostu odwołaj się do nazwy atrybutu bez przedrostka:<style name="MyStyle> <item name="typeface">roboto</item> </style>
źródło
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
źródło
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
źródło
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 twoim
onCreate
val typefaceUtil = TypefaceUtil() typefaceUtil.overridefonts(this,"SERIF","fonts/font_file.ttf")
Krok trzeci
dodaj to do swojego stylu
<item name="android:typeface">serif</item>
źródło
Nazwy czcionek należy pisać małymi literami, aby były widoczne w aplikacji i pracy.
źródło