webentwicklung-frage-antwort-db.com.de

Ist es möglich, eine benutzerdefinierte Schriftart für die gesamte Anwendung festzulegen?

Ich muss eine bestimmte Schriftart für meine gesamte Anwendung verwenden. Ich habe eine .ttf-Datei für dasselbe . Kann ich diese als Standardschriftart festlegen, beim Start der Anwendung starten und sie an anderer Stelle in der Anwendung verwenden? Wenn festgelegt, wie verwende ich es in meinen Layout-XMLs?

253
Samuh

Ja mit Nachdenken. Dies funktioniert ( basierend auf dieser Antwort ):

(Hinweis: Dies ist eine Problemumgehung, da benutzerdefinierte Schriftarten nicht unterstützt werden. Wenn Sie also diese Situation ändern möchten, müssen Sie die Android-Ausgabe hier ) stimmen. Hinweis: Lassen Sie keine "Ich auch" -Kommentare zu diesem Problem. Jeder, der es angestarrt hat, erhält eine E-Mail, wenn Sie das tun. Also "star" es bitte.

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

Sie müssen dann die wenigen Standardschriftarten überladen, zum Beispiel in einer application class:

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

Wenn Sie dieselbe Zeichensatzdatei verwenden, können Sie dies natürlich verbessern, indem Sie sie nur einmal laden.

Ich neige jedoch dazu, nur einen zu überschreiben, etwa "MONOSPACE", und dann einen Stil zu setzen, um die Anwendung dieser Schriftart zu erzwingen:

<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

Ich habe die Berichte in den Kommentaren untersucht, dass es nicht funktioniert und es scheint mit dem Thema Android:Theme.Material.Light inkompatibel zu sein.

Wenn dieses Thema für Sie nicht wichtig ist, verwenden Sie ein älteres Thema, z.

<style name="AppTheme" parent="Android:Theme.Holo.Light.DarkActionBar">
    <item name="Android:typeface">monospace</item>
</style>
444
weston

Es gibt eine große Bibliothek für benutzerdefinierte Schriftarten in Android: Kalligraphie

hier ist ein Beispiel, wie man es benutzt. 

in Gradle müssen Sie diese Zeile in die build.gradle -Datei Ihrer App einfügen:

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

und dann eine Klasse erstellen, die Application erweitert, und diesen Code schreiben:

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

und in der Aktivitätsklasse setzen Sie diese Methode vor onCreate:

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

und das letzte, was Ihre Manifestdatei so aussehen sollte:

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

und es ändert sich die gesamte Aktivität in Ihre Schriftart! es ist einfach und sauber! 

63
Shia G

Während dies nicht für eine gesamte Anwendung funktionieren würde, würde es für eine Aktivität funktionieren und könnte für jede andere Aktivität wiederverwendet werden. Ich habe meinen Code dank @ FR073N aktualisiert, um andere Ansichten zu unterstützen. Ich bin mir nicht sicher, ob es Probleme mit Buttons, RadioGroups usw. gibt, da diese Klassen alle TextView erweitern, sodass sie gut funktionieren sollten. Ich habe eine boolesche Bedingung für die Verwendung von Reflection hinzugefügt, da dies sehr hackig erscheint und die Leistung erheblich beeinträchtigen könnte.

Hinweis: Wie bereits erwähnt, funktioniert dies nicht für dynamische Inhalte! Dafür ist es möglich, diese Methode mit einer onCreateView- oder getView-Methode aufzurufen, erfordert jedoch zusätzlichen Aufwand.

/**
 * Recursively sets a {@link Typeface} to all
 * {@link TextView}s in a {@link ViewGroup}.
 */
public static final void setAppFont(ViewGroup mContainer, Typeface mFont, boolean reflect)
{
    if (mContainer == null || mFont == null) return;

    final int mCount = mContainer.getChildCount();

    // Loop through all of the children.
    for (int i = 0; i < mCount; ++i)
    {
        final View mChild = mContainer.getChildAt(i);
        if (mChild instanceof TextView)
        {
            // Set the font if it is a TextView.
            ((TextView) mChild).setTypeface(mFont);
        }
        else if (mChild instanceof ViewGroup)
        {
            // Recursively attempt another ViewGroup.
            setAppFont((ViewGroup) mChild, mFont);
        }
        else if (reflect)
        {
            try {
                Method mSetTypeface = mChild.getClass().getMethod("setTypeface", Typeface.class);
                mSetTypeface.invoke(mChild, mFont); 
            } catch (Exception e) { /* Do something... */ }
        }
    }
}

Um es zu benutzen, würden Sie so etwas tun:

final Typeface mFont = Typeface.createFromAsset(getAssets(),
"fonts/MyFont.ttf"); 
final ViewGroup mContainer = (ViewGroup) findViewById(
Android.R.id.content).getRootView();
HomeActivity.setAppFont(mContainer, mFont);

Hoffentlich hilft das.

47
Tom

In Summe:

Option # 1: Verwenden Sie Reflektion, um die Schriftart anzuwenden (Kombination von weston & Roger Huang ):

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) {
        if (isVersionGreaterOrEqualToLollipop()) {
            Map<String, Typeface> newMap = new HashMap<String, Typeface>();
            newMap.put("sans-serif", newTypeface);
            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 staticField = Typeface.class.getDeclaredField(staticTypefaceFieldName);
                staticField.setAccessible(true);
                staticField.set(null, newTypeface);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } 
        }
    }

} 

Verwendung in der Anwendungsklasse:

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

richten Sie einen Stil ein, um die Anwendung für diese Schriftart zu erzwingen (basierend auf lovefish ):

Pre-Lollipop:

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

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

Lutscher (API 21):

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

   <!-- Application theme. -->
   <style name="AppTheme" parent="AppBaseTheme">
       <item name="Android:textAppearance">@style/CustomTextAppearance</item>
   </style>

   <style name="CustomTextAppearance">
       <item name="Android:typeface">monospace</item>
   </style>
</resources>

Option2: Unterklasse jede Ansicht, in der Sie die Schriftart anpassen müssen, z. ListView, EditTextView, Button usw. (Antwort von Palani ):

public class CustomFontView extends TextView {

public CustomFontView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(); 
} 

public CustomFontView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(); 
} 

public CustomFontView(Context context) {
    super(context);
    init(); 
} 

private void init() { 
    if (!isInEditMode()) {
        Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "Futura.ttf");
        setTypeface(tf);
    } 
} 

Option 3: Implementieren Sie einen View-Crawler, der die View-Hierarchie Ihres aktuellen Bildschirms durchläuft:

Variante 1 ( Tom ) Antwort:

public static final void setAppFont(ViewGroup mContainer, Typeface mFont, boolean reflect)
{ 
    if (mContainer == null || mFont == null) return;

    final int mCount = mContainer.getChildCount();

    // Loop through all of the children. 
    for (int i = 0; i < mCount; ++i)
    { 
        final View mChild = mContainer.getChildAt(i);
        if (mChild instanceof TextView)
        { 
            // Set the font if it is a TextView. 
            ((TextView) mChild).setTypeface(mFont);
        } 
        else if (mChild instanceof ViewGroup)
        { 
            // Recursively attempt another ViewGroup. 
            setAppFont((ViewGroup) mChild, mFont);
        } 
        else if (reflect)
        { 
            try { 
                Method mSetTypeface = mChild.getClass().getMethod("setTypeface", Typeface.class);
                mSetTypeface.invoke(mChild, mFont); 
            } catch (Exception e) { /* Do something... */ }
        } 
    } 
} 

Verwendungszweck :

final ViewGroup mContainer = (ViewGroup) findViewById(
Android.R.id.content).getRootView();
HomeActivity.setAppFont(mContainer, Typeface.createFromAsset(getAssets(),
"fonts/MyFont.ttf"));

Variante 2: https://coderwall.com/p/qxxmaa/Android-use-a-custom-font-everywhere .

Option # 4: Verwenden Sie die Drittanbieter-Lib namens Kalligraphie .

Persönlich würde ich Option # 4 empfehlen, da dies eine Menge Kopfschmerzen erspart.

31
Phileo99

Ich möchte die Antwort von weston für API 21 Android 5.0 verbessern.

Ursache

Unter API 21 enthalten die meisten Textstile die Einstellung fontFamily wie:

<style name="TextAppearance.Material">
     <item name="fontFamily">@string/font_family_body_1_material</item>
</style>

Welche wendet die Standardschriftart Roboto Regular an:

<string name="font_family_body_1_material">sans-serif</string>

Die ursprüngliche Antwort kann keine Monospace-Schriftart anwenden, da Android: fontFamily dem Android: Schriftattribut ( reference ) eine höhere Priorität zuweist. Die Verwendung von Theme.Holo. * Ist eine gültige Problemumgehung, da keine Android: fontFamily-Einstellungen vorhanden sind.

Lösung

Da Android 5.0 die Systemschriftart in die statische Variable Typeface.sSystemFontMap ( reference ) geschrieben hat, können wir dieselbe Reflexionstechnik verwenden, um sie zu ersetzen:

protected static void replaceFont(String staticTypefaceFieldName,
        final Typeface newTypeface) {
    if (isVersionGreaterOrEqualToLollipop()) {
        Map<String, Typeface> newMap = new HashMap<String, Typeface>();
        newMap.put("sans-serif", newTypeface);
        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 staticField = Typeface.class
                    .getDeclaredField(staticTypefaceFieldName);
            staticField.setAccessible(true);
            staticField.set(null, newTypeface);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
28
Roger Huang

es ist sehr einfach ... 1. Laden Sie Ihre eigene Schriftart in Assets herunter. Schreiben Sie dann eine separate Klasse für die Textansicht wie folgt: Hier habe ich Futura-Schriftart verwendet

public class CusFntTextView extends TextView {

public CusFntTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
}

public CusFntTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

public CusFntTextView(Context context) {
    super(context);
    init();
}

private void init() {
    if (!isInEditMode()) {
        Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "Futura.ttf");
        setTypeface(tf);
    }
}

}

und mache folgendes in xml:

 <com.packagename.CusFntTextView
        Android:id="@+id/tvtitle"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"         
        Android:text="Hi Android"           
        Android:textAppearance="?android:attr/textAppearanceLarge"
      />
15
Palani

Ich würde auch vorschlagen, TextView und andere Steuerelemente zu erweitern, aber es wäre besser, wenn ich die Schrift in Konstrukten einrichte.

public FontTextView(Context context) {
    super(context);
    init();
}

public FontTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

public FontTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
}

protected void init() {
    setTypeface(Typeface.createFromAsset(getContext().getAssets(), AppConst.FONT));
}
9

Ich möchte die Antworten von weston und Roger Huang für API 21 Android Lollipop mit dem Thema "Theme.AppCompat" verbessern.

Unter Android 4.4

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

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

Über (gleich) API 5.0

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

   <!-- Application theme. -->
   <style name="AppTheme" parent="AppBaseTheme">
       <item name="Android:textAppearance">@style/CustomTextAppearance</item>
   </style>

   <style name="CustomTextAppearance">
       <item name="Android:typeface">monospace</item>
   </style>
</resources>

Und die FontsOverride -Datei ist die gleiche wie in weston s Antwort. Ich habe in diesen Handys getestet:

Nexus 5 (Android 5.1-Android-Primärsystem) 

ZTE V5 (Android 5.1 CM12.1) 

XIAOMI Hinweis (Android 4.4 MIUI6)

HUAWEI C8850 (Android 2.3.5 UNBEKANNT)

8
lovefish

Eine brillante Lösung kann hier gefunden werden: https://coderwall.com/p/qxxmaa/Android-use-a-custom-font-everywhere .

Erweitern Sie einfach Aktivitäten aus BaseActivity und schreiben Sie diese Methoden. Sie sollten auch Schriftarten wie hier beschrieben zwischenspeichern: https://stackoverflow.com/a/16902532/2914140 .


Nach einigen Recherchen habe ich Code geschrieben, der bei Samsung Galaxy Tab A (Android 5.0) funktioniert. Verwendeter Code von Weston und Roger Huang sowie https://stackoverflow.com/a/33236102/2914140 . Auch auf Lenovo TAB 2 A10-70L getestet, wo es nicht funktioniert. Ich habe hier eine Schrift "Comic Sans" eingefügt, um einen Unterschied zu erkennen.

import Android.content.Context;
import Android.graphics.Typeface;
import Android.os.Build;
import Android.util.Log;
import Java.lang.reflect.Field;
import Java.util.HashMap;
import Java.util.Map;

public class FontsOverride {
    private static final int BOLD = 1;
    private static final int BOLD_ITALIC = 2;
    private static final int ITALIC = 3;
    private static final int LIGHT = 4;
    private static final int CONDENSED = 5;
    private static final int THIN = 6;
    private static final int MEDIUM = 7;
    private static final int REGULAR = 8;

    private Context context;

    public FontsOverride(Context context) {
        this.context = context;
    }

    public void loadFonts() {
        Map<String, Typeface> fontsMap = new HashMap<>();
        fontsMap.put("sans-serif", getTypeface("comic.ttf", REGULAR));
        fontsMap.put("sans-serif-bold", getTypeface("comic.ttf", BOLD));
        fontsMap.put("sans-serif-italic", getTypeface("comic.ttf", ITALIC));
        fontsMap.put("sans-serif-light", getTypeface("comic.ttf", LIGHT));
        fontsMap.put("sans-serif-condensed", getTypeface("comic.ttf", CONDENSED));
        fontsMap.put("sans-serif-thin", getTypeface("comic.ttf", THIN));
        fontsMap.put("sans-serif-medium", getTypeface("comic.ttf", MEDIUM));
        overrideFonts(fontsMap);
    }

    private void overrideFonts(Map<String, Typeface> typefaces) {
        if (Build.VERSION.SDK_INT == 21) {
            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", "Cannot set custom fonts");
            }
        } else {
            try {
                for (Map.Entry<String, Typeface> entry : typefaces.entrySet()) {
                    final Field staticField = Typeface.class.getDeclaredField(entry.getKey());
                    staticField.setAccessible(true);
                    staticField.set(null, entry.getValue());
                }
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    private Typeface getTypeface(String fontFileName, int fontType) {
        final Typeface tf = Typeface.createFromAsset(context.getAssets(), "fonts/" + fontFileName);
        return Typeface.create(tf, fontType);
    }
}

Um den Code in der gesamten Anwendung auszuführen, sollten Sie in einer Klasse wie Application Folgendes schreiben:

    new FontsOverride(this).loadFonts();

Erstellen Sie einen Ordner "Schriftarten" in "Assets" und fügen Sie die benötigten Schriftarten dort hinzu. Eine einfache Anleitung finden Sie hier: https://stackoverflow.com/a/31697103/2914140 .

Das Lenovo-Gerät erhält fälschlicherweise einen Wert einer Schriftart. In den meisten Fällen wird Typeface.NORMAL zurückgegeben, manchmal auch null. Auch wenn eine TextView fett ist (im XML-Dateilayout). Siehe hier: TextView isBold gibt immer NORMAL zurück. Auf diese Weise ist ein Text auf einem Bildschirm immer in einer regulären Schriftart, nicht fett oder kursiv. Ich denke, es ist ein Fehler eines Produzenten.

7
CoolMind

Arbeiten für Xamarin.Android:

Klasse:

public class FontsOverride
{
    public static void SetDefaultFont(Context context, string staticTypefaceFieldName, string fontAssetName)
    {
        Typeface regular = Typeface.CreateFromAsset(context.Assets, fontAssetName);
        ReplaceFont(staticTypefaceFieldName, regular);
    }

    protected static void ReplaceFont(string staticTypefaceFieldName, Typeface newTypeface)
    {
        try
        {
            Field staticField = ((Java.Lang.Object)(newTypeface)).Class.GetDeclaredField(staticTypefaceFieldName);
            staticField.Accessible = true;
            staticField.Set(null, newTypeface);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

Anwendungsimplementierung:

namespace SomeAndroidApplication
{
    [Application]
    public class App : Application
    {
        public App()
        {

        }

        public App(IntPtr handle, JniHandleOwnership transfer)
            : base(handle, transfer)
        {

        }

        public override void OnCreate()
        {
            base.OnCreate();

            FontsOverride.SetDefaultFont(this, "MONOSPACE", "fonts/Roboto-Light.ttf");
        }
    }
}

Stil:

<style name="Theme.Storehouse" parent="Theme.Sherlock">
    <item name="Android:typeface">monospace</item>
</style>
6
Guy Micciche

Ab Android O ist es jetzt möglich direkt aus dem XML zu definieren und mein Fehler ist jetzt geschlossen!

Siehe hier für Details

TL; DR:

Zuerst müssen Sie Ihre Schriftarten zum Projekt hinzufügen

Zweitens fügen Sie eine Schriftfamilie hinzu:

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

Schließlich können Sie die Schrift in einem Layout oder Stil verwenden:

<TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:fontFamily="@font/lobster"/>

<style name="customfontstyle" parent="@Android:style/TextAppearance.Small">
    <item name="Android:fontFamily">@font/lobster</item>
</style>

Genießen!

5
Sam

Sie können benutzerdefinierte Schriftarten für jedes Layout einzeln festlegen, indem Sie nur einen Funktionsaufruf aus jedem Layout übergeben, indem Sie dessen Stammansicht übergeben. Erstellen Sie zunächst einen Singelton-Ansatz für den Zugriff auf ein solches Schriftobjekt 

 public class Font {
    private static Font font;
    public Typeface ROBO_LIGHT;

    private Font() {

    }

    public static Font getInstance(Context context) {
        if (font == null) {
            font = new Font();
            font.init(context);
        }
        return font;

    }

    public void init(Context context) {

        ROBO_LIGHT = Typeface.createFromAsset(context.getAssets(),
                "Roboto-Light.ttf");
    }

}

Sie können in der obigen Klasse verschiedene Schriftarten definieren. Jetzt Definieren Sie eine Schriftarten-Helper-Klasse, in der Schriftarten angewendet werden: 

   public class FontHelper {

    private static Font font;

    public static void applyFont(View parentView, Context context) {

        font = Font.getInstance(context);

        apply((ViewGroup)parentView);

    }

    private static void apply(ViewGroup parentView) {
        for (int i = 0; i < parentView.getChildCount(); i++) {

            View view = parentView.getChildAt(i);

//You can add any view element here on which you want to apply font 

            if (view instanceof EditText) {

                ((EditText) view).setTypeface(font.ROBO_LIGHT);

            }
            if (view instanceof TextView) {

                ((TextView) view).setTypeface(font.ROBO_LIGHT);

            }

            else if (view instanceof ViewGroup
                    && ((ViewGroup) view).getChildCount() > 0) {
                apply((ViewGroup) view);
            }

        }

    }

}

Im obigen Code wende ich Schriftarten nur auf textView und EditText an. Sie können Schriftarten auch auf andere Ansichtselemente auf ähnliche Weise anwenden. Sie müssen nur die ID Ihrer Stammansichtsgruppe an die obige Apply-Schriftmethode übergeben. Ihr Layout ist zum Beispiel:

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical"
    Android:id="@+id/mainParent"
    tools:context="${relativePackage}.${activityClass}" >

    <RelativeLayout
        Android:id="@+id/mainContainer"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_above="@+id/homeFooter"
        Android:layout_below="@+id/edit" >

        <ImageView
            Android:id="@+id/PreviewImg"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:src="@drawable/abc_list_longpressed_holo"
            Android:visibility="gone" />

        <RelativeLayout
            Android:id="@+id/visibilityLayer"
            Android:layout_width="match_parent"
            Android:layout_height="fill_parent" >

            <ImageView
                Android:id="@+id/UseCamera"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:layout_alignParentTop="true"
                Android:layout_centerHorizontal="true"
                Android:src="@drawable/camera" />

            <TextView
                Android:id="@+id/tvOR"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:layout_below="@+id/UseCamera"
                Android:layout_centerHorizontal="true"
                Android:layout_marginTop="20dp"
                Android:text="OR"
                Android:textSize="30dp" />

            <TextView
                Android:id="@+id/tvAND"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:layout_centerHorizontal="true"
                Android:layout_marginTop="20dp"
                Android:text="OR"
                Android:textSize="30dp" />

</RelativeLayout>

Im obigen Layout ist die übergeordnete Stamm-ID "Main Parent" und lässt jetzt die Schriftart anwenden 

public class MainActivity extends BaseFragmentActivity {

    private EditText etName;
    private EditText etPassword;
    private TextView tvTitle;
    public static boolean isHome = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

       Font font=Font.getInstance(getApplicationContext());
        FontHelper.applyFont(findViewById(R.id.mainParent),          getApplicationContext());
   }    
}

Prost :) 

4
Ajji

Ich würde vorschlagen, TextView zu erweitern und immer Ihre benutzerdefinierte TextView in Ihren XML-Layouts zu verwenden oder wo immer Sie eine TextView benötigen. Überschreiben Sie in Ihrer benutzerdefinierten Textansicht setTypeface.

@Override
public void setTypeface(Typeface tf, int style) {
    //to handle bold, you could also handle italic or other styles here as well
    if (style == 1){
        tf = Typeface.createFromAsset(getContext().getApplicationContext().getAssets(), "MuseoSans700.otf");
    }else{
        tf = Typeface.createFromAsset(getContext().getApplicationContext().getAssets(), "MuseoSans500.otf");
    }
    super.setTypeface(tf, 0);
}
3
Sam Dozor

Ich habe eine Klasse geschrieben, die den Ansichten in der aktuellen Ansichtshierarchie eine Schriftart zuordnet, und basiert auf den aktuellen Eigenschaften der Schriftart (fett, normal, Sie können bei Bedarf andere Stile hinzufügen):

public final class TypefaceAssigner {

public final Typeface DEFAULT;
public final Typeface DEFAULT_BOLD;

@Inject
public TypefaceAssigner(AssetManager assetManager) {
    DEFAULT = Typeface.createFromAsset(assetManager, "TradeGothicLTCom.ttf");
    DEFAULT_BOLD = Typeface.createFromAsset(assetManager, "TradeGothicLTCom-Bd2.ttf");
}

public void assignTypeface(View v) {
    if (v instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) v).getChildCount(); i++) {
            View view = ((ViewGroup) v).getChildAt(i);
            if (view instanceof ViewGroup) {
                setTypeface(view);
            } else {
                setTypeface(view);
            }
        }
    } else {
        setTypeface(v);
    }
}

private void setTypeface(View view) {
    if (view instanceof TextView) {
        TextView textView = (TextView) view;
        Typeface typeface = textView.getTypeface();
        if (typeface != null && typeface.isBold()) {
            textView.setTypeface(DEFAULT_BOLD);
        } else {
            textView.setTypeface(DEFAULT);
        }
    }
}
}

Nun in allen Fragmenten in onViewCreated oder onCreateView, in allen Aktivitäten in onCreate und in allen Ansichtsadaptern in getView oder newView einfach Folgendes aufrufen:

typefaceAssigner.assignTypeface(view);
2
Ivan Kravchenko

Toms Lösung funktioniert hervorragend, funktioniert jedoch nur mit TextView und EditText.

Wenn Sie die meisten Ansichten abdecken möchten (RadioGroup, TextView, Checkbox ...), habe ich eine Methode erstellt: 

protected void changeChildrenFont(ViewGroup v, Typeface font){
    for(int i = 0; i < v.getChildCount(); i++){

        // For the ViewGroup, we'll have to use recursivity
        if(v.getChildAt(i) instanceof ViewGroup){
            changeChildrenFont((ViewGroup) v.getChildAt(i), font);
        }
        else{
            try {
                Object[] nullArgs = null;
                //Test wether setTypeface and getTypeface methods exists
                Method methodTypeFace = v.getChildAt(i).getClass().getMethod("setTypeface", new Class[] {Typeface.class, Integer.TYPE});
                //With getTypefaca we'll get back the style (Bold, Italic...) set in XML
                Method methodGetTypeFace = v.getChildAt(i).getClass().getMethod("getTypeface", new Class[] {});
                Typeface typeFace = ((Typeface)methodGetTypeFace.invoke(v.getChildAt(i), nullArgs));
                //Invoke the method and apply the new font with the defined style to the view if the method exists (textview,...)
                methodTypeFace.invoke(v.getChildAt(i), new Object[] {font, typeFace == null ? 0 : typeFace.getStyle()});
            }
            //Will catch the view with no such methods (listview...)
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Diese Methode holt den in XML eingestellten Stil der Ansicht (fett, kursiv ...) zurück und wendet sie an, falls vorhanden. 

Für die ListView erstelle ich immer einen Adapter und setze die Schriftart in getView. 

2
FR073N

Schließlich erkannte Google den Schweregrad dieses Problems (das Anwenden einer benutzerdefinierten Schriftart auf die Komponenten der Benutzeroberfläche), und sie entwickelten eine saubere Lösung.

Zuerst müssen Sie ein Update durchführen, um die Bibliothek 26+ zu unterstützen (möglicherweise müssen Sie auch Ihr Gradle {4.0+}, Android Studio, aktualisieren). Anschließend können Sie einen neuen Ressourcenordner mit dem Namen "font" erstellen. In diesem Ordner können Sie Ihre Fontressourcen ablegen (.tff, ...) . Dann müssen Sie die Standard-App überschreiben und Ihre benutzerdefinierte Schriftart erzwingen. :)

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="Android:fontFamily">@font/my_custom_font</item>
</style>

Hinweis: Wenn Sie Geräte mit älterer API als 16 unterstützen möchten, müssen Sie anstelle von Android einen App-Namespace verwenden. 

1
Mr.Q

in api 26 mit build.gradle 3.0.0 und höher können Sie ein Schriftverzeichnis in res erstellen und diese Zeile in Ihrem Stil verwenden

<item name="Android:fontFamily">@font/your_font</item>

zur Änderung von build.gradle verwenden Sie dies in Ihren build.gradle-Abhängigkeiten

classpath 'com.Android.tools.build:gradle:3.0.0'

Ich möchte auch die Antwort von weston für API 21 Android 5.0 verbessern.

Ich hatte das gleiche Problem auf meinem Samsung s5, wenn Sie die DEFAULT-Schriftart verwenden. (mit den anderen Schriftarten funktioniert es gut)

Ich habe es geschafft, dass es funktioniert, indem ich in XML-Dateien für jede Textansicht oder jeden Button den typeface ("sans") setze

<TextView
Android:layout_width="match_parent"
Android:layout_height="39dp"
Android:textColor="@color/abs__background_holo_light"
Android:textSize="12sp"
Android:gravity="bottom|center"
Android:typeface="sans" />

und in MyApplication Class:

public class MyApplication extends Application {
    @Override
    public void onCreate() {
    TypefaceUtil.overrideFont(getApplicationContext(), "SANS_SERIF",
    "fonts/my_font.ttf");
    }
}

Ich hoffe es hilft.

0
stevenwood

Um die Standardschriftfamilie der TextViews zu ändern, überschreiben Sie textViewStyle in Ihrem App-Design.

Verwenden Sie zur Verwendung der benutzerdefinierten Schriftart in fontFamily Fontressourcen, die sich in der Unterstützungsbibliothek befinden. 

Die Funktion wurde in Android 26 hinzugefügt, aber über Supportlib zu älteren Versionen zurückportiert.

https://developer.Android.com/guide/topics/resources/font-resource.htmlhttps://developer.Android.com/guide/topics/ui/look-and- feel/fonts-in-xml.html # using-support-lib

0
Siyamed

Kalligraphie funktioniert ziemlich gut, ist aber nicht für mich geeignet, da sie keine unterschiedlichen Schriftgrade (Fett, Kursiv usw.) für eine Schriftfamilie unterstützt.

Ich habe also Fontain ausprobiert, mit dem Sie benutzerdefinierte Ansichten definieren und benutzerdefinierte Schriftfamilien anwenden können.

um Fontain verwenden zu können, sollten Sie Ihrem App-Modul build.gradle Folgendes hinzufügen:

compile 'com.scopely:fontain:1.0.0'

Anstelle von regulärer TextView sollten Sie dann FontTextView verwenden

Beispiel für FontTextView mit Großbuchstaben und fettem Inhalt:

 <com.scopely.fontain.views.FontTextView
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:background="@Android:color/black"
            Android:textColor="@Android:color/white"
            Android:textSize="11dp"
            Android:gravity="center"
            Android:id="@+id/tv1"
            app:font_family="myCustomFont"
            app:caps_mode="characters"
            app:font_weight="BOLD"/>
0
Cris

Seit der Veröffentlichung von Android Oreo und seiner Support-Bibliothek (26.0.0) ist dies problemlos möglich. Siehe diese Antwort in einer anderen Frage.

Grundsätzlich wird Ihr endgültiger Stil so aussehen:

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
   <item name="fontFamily">@font/your_font</item> <!-- target Android sdk versions < 26 and > 14 -->
</style>
0

Diese - Lösung funktioniert in einigen Situationen nicht richtig.
.__ Ich erweitere es also:

SchriftartenReplacer.Java

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        FontsReplacer.replaceFonts(this);
        super.onCreate();
    }

}

https://Gist.github.com/orwir/6df839e3527647adc2d56bfadfaad805

0
Igor
package com.theeasylearn.demo.designdemo;
import Android.content.Context;
import Android.graphics.Typeface;
import Android.util.AttributeSet;
import Android.widget.TextView;

public class MyButton extends TextView {

    public MyButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyButton(Context context) {
        super(context);
        init();
    }

    private void init() {

            Typeface tf =
                    Typeface.createFromAsset(
                            getContext().getAssets(), "angelina.TTF");
            setTypeface(tf);

    }

}