it-swarm.com.de

Benutzerdefinierte Schriftarten und XML-Layouts (Android)

Ich versuche, ein GUI-Layout unter Verwendung von XML-Dateien in Android zu definieren. Soweit ich herausfinden kann, gibt es keine Möglichkeit festzulegen, dass Ihre Widgets in XML-Dateien eine benutzerdefinierte Schriftart (z. B. eine, die Sie in assets/font/platziert haben) verwendet.

Ich weiß, dass ich im Java-Code die Schriftart jedes Widgets manuell mit eindeutigen IDs ändern konnte. Alternativ könnte ich über alle Widgets in Java iterieren, um diese Änderung vorzunehmen. Dies wäre jedoch wahrscheinlich sehr langsam.

Welche anderen Möglichkeiten habe ich? Gibt es bessere Möglichkeiten, Widgets mit einem benutzerdefinierten Aussehen zu erstellen? Ich möchte nicht unbedingt die Schriftart für jedes neue Widget, das ich hinzufüge, manuell ändern müssen.

171
DrDefrost

Sie können TextView erweitern, um benutzerdefinierte Schriftarten festzulegen, wie ich hier gelernt habe.

TextViewPlus.Java: 

package com.example;

import Android.content.Context;
import Android.content.res.TypedArray;
import Android.graphics.Typeface;
import Android.util.AttributeSet;
import Android.util.Log;
import Android.widget.TextView;

public class TextViewPlus extends TextView {
    private static final String TAG = "TextView";

    public TextViewPlus(Context context) {
        super(context);
    }

    public TextViewPlus(Context context, AttributeSet attrs) {
        super(context, attrs);
        setCustomFont(context, attrs);
    }

    public TextViewPlus(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setCustomFont(context, attrs);
    }

    private void setCustomFont(Context ctx, AttributeSet attrs) {
        TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.TextViewPlus);
        String customFont = a.getString(R.styleable.TextViewPlus_customFont);
        setCustomFont(ctx, customFont);
        a.recycle();
    }

    public boolean setCustomFont(Context ctx, String asset) {
        Typeface tf = null;
        try {
        tf = Typeface.createFromAsset(ctx.getAssets(), asset);  
        } catch (Exception e) {
            Log.e(TAG, "Could not get typeface: "+e.getMessage());
            return false;
        }

        setTypeface(tf);  
        return true;
    }

}

attrs.xml: (in res/values)

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="TextViewPlus">
        <attr name="customFont" format="string"/>
    </declare-styleable>
</resources>

main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:foo="http://schemas.Android.com/apk/res/com.example"
    Android:orientation="vertical" Android:layout_width="fill_parent"
    Android:layout_height="fill_parent">

    <com.example.TextViewPlus
        Android:id="@+id/textViewPlus1"
        Android:layout_height="match_parent"
        Android:layout_width="match_parent"
        Android:text="@string/showingOffTheNewTypeface"
        foo:customFont="saxmono.ttf">
    </com.example.TextViewPlus>
</LinearLayout>

Sie würden "saxmono.ttf" im Ordner assets ablegen.

UPDATE 01.08.13

Bei dieser Methode gibt es ernsthafte Bedenken hinsichtlich des Speichers. Siehe chedabobs Kommentar unten.

218
peter

Ich bin drei Jahre zu spät für die Party :( Dies könnte jedoch für jemanden nützlich sein, der über diesen Beitrag stolpern könnte.

Ich habe eine Bibliothek geschrieben, in der Schriftarten zwischengespeichert werden. Außerdem können Sie benutzerdefinierte Schriftarten direkt aus XML angeben. Sie finden die Bibliothek hier .

So würde Ihr XML-Layout aussehen, wenn Sie es verwenden.

<com.mobsandgeeks.ui.TypefaceTextView
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="@string/hello_world"
    geekui:customTypeface="fonts/custom_font.ttf" />
35

Dies kann etwas spät sein, aber Sie müssen eine Singleton-Klasse erstellen, die die benutzerdefinierte Schriftart zurückgibt, um Speicherverluste zu vermeiden.

TypeFace-Klasse:

public class OpenSans {

private static OpenSans instance;
private static Typeface typeface;

public static OpenSans getInstance(Context context) {
    synchronized (OpenSans.class) {
        if (instance == null) {
            instance = new OpenSans();
            typeface = Typeface.createFromAsset(context.getResources().getAssets(), "open_sans.ttf");
        }
        return instance;
    }
}

public Typeface getTypeFace() {
    return typeface;
}
}

Benutzerdefinierte Textansicht:

public class NativelyCustomTextView extends TextView {

    public NativelyCustomTextView(Context context) {
        super(context);
        setTypeface(OpenSans.getInstance(context).getTypeFace());
    }

    public NativelyCustomTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setTypeface(OpenSans.getInstance(context).getTypeFace());
    }

    public NativelyCustomTextView(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
        setTypeface(OpenSans.getInstance(context).getTypeFace());
    }

}

Von xml:

<com.yourpackage.views.NativelyCustomTextView
            Android:id="@+id/natively_text_view"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_centerHorizontal="true"
            Android:layout_margin="20dp"
            Android:text="@string/natively"
            Android:textSize="30sp" /> 

Programmatisch:

TextView programmaticallyTextView = (TextView) 
       findViewById(R.id.programmatically_text_view);

programmaticallyTextView.setTypeface(OpenSans.getInstance(this)
                .getTypeFace());
18

Alte Frage, aber ich wünschte, ich würde diese Antwort hier lesen, bevor ich mit meiner eigenen Suche nach einer guten Lösung begann. Kalligraphie erweitert das Android:fontFamily-Attribut, um Unterstützung für benutzerdefinierte Schriftarten in Ihrem Asset-Ordner hinzuzufügen.

<TextView 
  Android:text="@string/hello_world"
  Android:layout_width="wrap_content"
  Android:layout_height="wrap_content"
  Android:fontFamily="fonts/Roboto-Bold.ttf"/>

Das einzige, was Sie tun müssen, um es zu aktivieren, ist das Anhängen an den Kontext der Aktivität, die Sie verwenden:

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

Sie können auch Ihr eigenes benutzerdefiniertes Attribut angeben, um Android:fontFamily zu ersetzen.

Es funktioniert auch in Themen, einschließlich der AppTheme.

13
thoutbeckers

Der beste Weg, dies zu tun Ab der Vorschau für Android O ist dies so 
1.) Klicken Sie mit der rechten Maustaste auf den Ordner res und wechseln Sie zu New> Android-Ressourcenverzeichnis. Das neue
Das Ressourcenverzeichnis-Fenster wird angezeigt.
2.) Wählen Sie in der Liste Ressourcentyp font aus und klicken Sie auf OK.
3.) Fügen Sie Ihre Font-Dateien im Font-Ordner hinzu. Die folgende Ordnerstruktur generiert R.font.dancing_script, R.font.la_la und R.font.ba_ba.
4.) Doppelklicken Sie auf eine Schriftartdatei, um eine Vorschau der Schriftarten der Datei im Editor anzuzeigen.

Als Nächstes müssen wir eine Schriftfamilie erstellen

1.) Klicken Sie mit der rechten Maustaste auf den Schriftartenordner und gehen Sie zu Neu> Ressourcendatei für Schriftarten. Das Fenster "Neue Ressourcendatei" wird angezeigt.
2.) Geben Sie den Dateinamen ein und klicken Sie auf OK. Die neue XML-Schriftartressource wird im Editor geöffnet.
3.) Schließen Sie jede Schriftartdatei, den Stil und das Gewichtsattribut in das Font-Tag-Element ein. Das folgende XML veranschaulicht das Hinzufügen von fontbezogenen Attributen in der Fontressourcen-XML:

<?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/hey_regular" />
    <font
    Android:fontStyle="italic"
    Android:fontWeight="400"
    Android:font="@font/hey_bababa" />
</font-family>

Hinzufügen von Schriftarten zu einer Textansicht:

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

Wie aus der Dokumentation 

Mit Schriften arbeiten

alle Schritte sind korrekt.

7
jeevan s

Verwenden von DataBinding :

@BindingAdapter({"bind:font"})
public static void setFont(TextView textView, String fontName){
 textView.setTypeface(Typeface.createFromAsset(textView.getContext().getAssets(), "fonts/" + fontName));
}

In XML:

<TextView
app:font="@{`Source-Sans-Pro-Regular.ttf`}"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"/>

schriftdatei muss in assets/fonts/ sein

7
Chulo

Wenn Sie nur eine Schriftart hinzufügen möchten und weniger Code schreiben möchten, können Sie eine eigene TextView für Ihre spezifische Schriftart erstellen. Siehe Code unten.

package com.yourpackage;
import Android.content.Context;
import Android.graphics.Typeface;
import Android.util.AttributeSet;
import Android.widget.TextView;

public class FontTextView extends TextView {
    public static Typeface FONT_NAME;


    public FontTextView(Context context) {
        super(context);
        if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "fonts/FontName.otf");
        this.setTypeface(FONT_NAME);
    }
    public FontTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "fonts/FontName.otf");
        this.setTypeface(FONT_NAME);
    }
    public FontTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "fonts/FontName.otf");
        this.setTypeface(FONT_NAME);
    }
}

In main.xml können Sie jetzt Ihre Textansicht folgendermaßen hinzufügen:

<com.yourpackage.FontTextView
    Android:id="@+id/tvTimer"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="" />
7
Tore Rudberg

Erweitern Sie TextView und geben Sie ihm ein benutzerdefiniertes Attribut, oder verwenden Sie einfach das Android: Tag-Attribut, um einen String der Schriftart zu übergeben, die Sie verwenden möchten. Sie müssen eine Konvention auswählen und sich daran halten, z. B. werden alle meine Schriftarten im Ordner res/assets/fonts/abgelegt, damit Ihre TextView-Klasse weiß, wo sie zu finden sind. Dann setzen Sie in Ihrem Konstruktor die Schrift nach dem Super-Aufruf einfach manuell. 

5
schwiz

Benutzerdefinierte Schriftarten können nur über den Quellcode verwendet werden.

Denken Sie daran, dass Android auf Geräten mit sehr begrenzten Ressourcen ausgeführt wird und Schriftarten möglicherweise viel Arbeitsspeicher erfordern. Die integrierten Droid-Schriftarten wurden speziell erstellt und, wenn Sie feststellen, viele Zeichen und Verzierungen fehlen.

4
Tareq Sha

Ich könnte eine einfache Antwort auf die Frage haben, ohne das TextView zu erweitern und einen langen Code zu implementieren.

Code:

 TextView tv = (TextView) findViewById(R.id.textview1);
    tv.setTypeface(Typeface.createFromAsset(getAssets(), "font.ttf"));

Legen Sie die benutzerdefinierte Schriftartdatei wie üblich im Assets-Ordner ab und versuchen Sie es. Es funktioniert für mich ... Ich verstehe nur nicht, warum Peter so einen riesigen Code für diese einfache Sache gegeben hat oder er seine Antwort in der alten Version gegeben hat.

2
San

Kann auch in der XML definiert werden, ohne benutzerdefinierte Klassen zu erstellen

style.xml

<style name="ionicons" parent="Android:TextAppearance">
    <!-- Custom Attr-->
    <item name="fontPath">fonts/ionicons.ttf</item>
</style>

activity_main.xml

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
              xmlns:app="http://schemas.Android.com/apk/res-auto"
              Android:layout_width="match_parent"
              Android:layout_height="match_parent"
              Android:orientation="vertical" >
    <Button
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:textAppearance="@style/ionicons"
        Android:text=""/>
</LinearLayout>

Ein kurzer Hinweis, da ich nur immer vergessen habe, wo die Schriften abgelegt werden sollen, muss sich die Schrift in assets befinden und dieser Ordner befindet sich auf derselben Ebene wie res und src, in meinem Fall ist es assets/fonts/ionicons.ttf

Aktualisiert Root-Layout hinzugefügt, da diese Methode xmlns:app="http://schemas.Android.com/apk/res-auto" Benötigt, um zu funktionieren

Update 2 Ich habe eine Bibliothek vergessen, die ich zuvor installiert habe. Kalligraphie

2
norman784

Es gibt zwei Möglichkeiten, die Schriftarten anzupassen:

!!! meine benutzerdefinierte Schriftart in assets/fonts/iran_sans.ttf

Weg 1: Refrection Typeface.class ||| bester Weg

rufen Sie FontsOverride.setDefaultFont () in der Klasse Application auf. Dieser Code bewirkt, dass alle Softwareschriftarten geändert werden, auch Toasts-Schriftarten 

AppController.Java

public class AppController extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        //Initial Font
        FontsOverride.setDefaultFont(getApplicationContext(), "MONOSPACE", "fonts/iran_sans.ttf");

    }
}

FontsOverride.Java

public class FontsOverride {

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

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

Weg 2: setTypeface verwenden

für eine spezielle Ansicht rufen Sie einfach setTypeface () auf, um die Schriftart zu ändern.

CTextView.Java

public class CTextView extends TextView {

    public CTextView(Context context) {
        super(context);
        init(context,null);
    }

    public CTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context,attrs);
    }

    public CTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context,attrs);
    }

    @RequiresApi(api = Build.VERSION_CODES.Lollipop)
    public CTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context,attrs);
    }

    public void init(Context context, @Nullable AttributeSet attrs) {

        if (isInEditMode())
            return;

        // use setTypeface for change font this view
        setTypeface(FontUtils.getTypeface("fonts/iran_sans.ttf"));

    }
}

FontUtils.Java

public class FontUtils {

    private static Hashtable<String, Typeface> fontCache = new Hashtable<>();

    public static Typeface getTypeface(String fontName) {
        Typeface tf = fontCache.get(fontName);
        if (tf == null) {
            try {
                tf = Typeface.createFromAsset(AppController.getInstance().getApplicationContext().getAssets(), fontName);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
            fontCache.put(fontName, tf);
        }
        return tf;
    }

}
1
Rasoul Miri

Peters Antwort ist die beste, aber Sie können diese verbessern, indem Sie die styles.xml von Android verwenden, um Ihre Schriftarten für alle Textansichten in Ihrer App anzupassen.

Mein Code ist hier

1
Jelle

Hier ist ein Tutorial, in dem Sie erfahren, wie Sie eine benutzerdefinierte Schriftart wie @peter einrichten: http://responsiveandroid.com/2012/03/15/custom-fonts-in-Android-widgets.html

es hat auch Rücksicht auf mögliche Speicherlecks ala http://code.google.com/p/Android/issues/detail?id=9904 . Das Tutorial enthält auch ein Beispiel zum Festlegen einer benutzerdefinierten Schriftart für eine Schaltfläche.

0
browep

Sie können leicht eine benutzerdefinierte Textansicht-Klasse erstellen: -

Also, was Sie zuerst tun müssen, machen Sie Custom textview class, die mit AppCompatTextView erweitert wurde.

public class CustomTextView extends AppCompatTextView {
    private int mFont = FontUtils.FONTS_NORMAL;
    boolean fontApplied;

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

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

    public CustomTextView(Context context) {
        super(context);
        init(null, context);
    }

    protected void init(AttributeSet attrs, Context cxt) {
        if (!fontApplied) {
            if (attrs != null) {
                mFont = attrs.getAttributeIntValue(
                        "http://schemas.Android.com/apk/res-auto", "Lato-Regular.ttf",
                        -1);
            }
            Typeface typeface = getTypeface();
            int typefaceStyle = Typeface.NORMAL;
            if (typeface != null) {
                typefaceStyle = typeface.getStyle();
            }
            if (mFont > FontUtils.FONTS) {
                typefaceStyle = mFont;
            }
            FontUtils.applyFont(this, typefaceStyle);
            fontApplied = true;
        }
    }
}

Bei jedem Aufruf der benutzerdefinierten Textansicht erhalten wir den int-Wert vom Attribut int fontValue = attrs.getAttributeIntValue("http://schemas.Android.com/apk/res-auto","Lato-Regular.ttf",-1).

Oder

GetTypeface () kann auch aus der Ansicht abgerufen werden, die wir in unserem XML-Code (Android:textStyle="bold|normal|italic") festgelegt haben. Also mach was immer du willst.

Jetzt machen wir FontUtils, um eine beliebige .ttf-Schriftart in unsere Ansicht zu setzen.

public class FontUtils {

    public static final int FONTS = 1;
    public static final int FONTS_NORMAL = 2;
    public static final int FONTS_BOLD = 3;
    public static final int FONTS_BOLD1 = 4;

    private static Map<String, Typeface> TYPEFACE = new HashMap<String, Typeface>();

    static Typeface getFonts(Context context, String name) {
        Typeface typeface = TYPEFACE.get(name);
        if (typeface == null) {
            typeface = Typeface.createFromAsset(context.getAssets(), name);
            TYPEFACE.put(name, typeface);
        }
        return typeface;
    }

    public static void applyFont(TextView tv, int typefaceStyle) {

        Context cxt = tv.getContext();
        Typeface typeface;

        if(typefaceStyle == Typeface.BOLD_ITALIC) {
            typeface = FontUtils.getFonts(cxt, "FaktPro-Normal.ttf");
        }else if (typefaceStyle == Typeface.BOLD || typefaceStyle == SD_FONTS_BOLD|| typefaceStyle == FONTS_BOLD1) {
            typeface = FontUtils.getFonts(cxt, "FaktPro-SemiBold.ttf");
        } else if (typefaceStyle == Typeface.ITALIC) {
            typeface = FontUtils.getFonts(cxt, "FaktPro-Thin.ttf");
        } else {
            typeface = FontUtils.getFonts(cxt, "FaktPro-Normal.ttf");
        }
        if (typeface != null) {
            tv.setTypeface(typeface);
        }
    }
}
0
duggu

Es kann nützlich sein zu wissen, dass Sie ab Android 8.0 (API Level 26) eine benutzerdefinierte Schriftart in XML verwenden verwenden können.

Sie können auf die folgende Weise eine benutzerdefinierte Schriftart auf die gesamte Anwendung anwenden.

  1. Legen Sie die Schriftart in den Ordner res/font.

  2. Verwenden Sie es in res/values/styles.xml im Anwendungsthema . <style name="AppTheme" parent="{whatever you like}"> <item name="Android:fontFamily">@font/myfont</item> </style>

0
Vic