Android: Ingin menyetel font khusus untuk seluruh aplikasi, bukan runtime

100

Apakah mungkin untuk mengatur font khusus di setiap kontrol aplikasi? Dan belum tentu runtime? (yaitu dari xml jika memungkinkan atau hanya sekali untuk seluruh aplikasi dalam file JAVA)

Saya dapat mengatur font untuk satu kontrol dari kode ini.

public static void setFont(TextView textView) {
    Typeface tf = Typeface.createFromAsset(textView.getContext()
            .getAssets(), "fonts/BPreplay.otf");

    textView.setTypeface(tf);

}

Dan masalah dengan kode ini adalah harus dipanggil untuk setiap kontrol. Dan saya ingin memanggil ini atau metode serupa sekali, atau jika mungkin mengatur properti dalam xml. Apa itu mungkin?

Prasham
sumber
6
Mungkin Anda dapat menulis kontrol kustom dengan memperluas TextView dan mengatur font di konstruktor bisa menjadi pilihan, Kemudian Anda dapat menggunakan kontrol ini di seluruh aplikasi di tempat textview Anda. juga untuk menghemat memori u dapat mencegah pemuatan sumber daya dengan menggunakan jenis huruf statis.
Varun
@ Varun: ide ini dapat menghemat waktu saya, tetapi saya harus mengatur setiap kontrol, dan menulis kontrol khusus untuk masing-masing akan menjadi cara yang lebih lama daripada mengatur runtime font, bagaimana menurut Anda? (Namun +1 untuk menulis kontrol khusus)
Prasham
Anda mungkin ingin menulis hanya satu kontrol kustom yang memperluas textView dan satu-satunya modifikasi adalah pengaturan jenis huruf. Dengan menggunakan kontrol cusotm dalam file tata letak Anda tidak harus melakukannya secara manual setiap waktu untuk setiap textview dan Anda masih dapat yakin bahwa Anda menggunakan font yang Anda inginkan.
Varun
Bagaimana dengan menulis kebiasaan VIEWdaripada menulis a custom text viewdan a custom button viewsecara terpisah? Persyaratan saya adalah untuk setiap kontrol, dan tampilan teks hanyalah sebuah contoh. Maaf, saya lupa menyebutkannya .. :-(
Prasham
1
Lihat pertanyaan satckoverflow stackoverflow.com/questions/2711858/… ini membantu Anda.
Ashwini

Jawaban:

123

EDIT : Jadi sudah lama, dan saya ingin menambahkan apa yang menurut saya adalah cara terbaik untuk melakukan ini, dan melalui XML tidak kurang!

Jadi pertama-tama, Anda ingin membuat kelas baru yang menimpa Tampilan apa pun yang ingin Anda sesuaikan. (mis. ingin Tombol dengan jenis huruf kustom? Perluas Button). Mari kita buat contoh:

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

Sekarang, jika Anda tidak memilikinya, tambahkan dokumen XML di bawah res/values/attrs.xml, dan tambahkan:

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

Oke, jadi setelah itu, mari kita kembali ke parseAttributes() metode dari sebelumnya:

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

Sekarang Anda sudah siap. Anda dapat menambahkan lebih banyak atribut untuk tentang apa saja (Anda dapat menambahkan atribut lain untuk typefaceStyle - tebal, miring, dll.) Tetapi sekarang mari kita lihat cara menggunakannya:

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

Itu xmlns:custom garis benar-benar dapat apa-apa, tapi konvensi adalah apa yang ditunjukkan di atas. Yang penting itu unik, dan itulah mengapa nama paket digunakan. Sekarang Anda cukup menggunakan custom:awalan untuk atribut Anda, dan android:awalan untuk atribut android.

Satu hal terakhir: jika Anda ingin menggunakan ini dalam gaya ( res/values/styles.xml), Anda tidak boleh menambahkan xmlns:custombaris. Cukup rujuk nama atribut tanpa awalan:

<style name="MyStyle>
    <item name="typeface">roboto</item>
</style>

                               (PREVIOUS ANSWER)

Menggunakan jenis huruf khusus di Android

Ini akan membantu. Pada dasarnya, tidak ada cara untuk melakukan ini dalam XML, dan sejauh yang saya tahu, tidak ada cara yang lebih mudah untuk melakukannya dalam kode. Anda selalu bisa memiliki metode setLayoutFont () yang membuat jenis huruf satu kali, lalu menjalankan setTypeface () untuk masing-masing. Anda hanya perlu memperbaruinya setiap kali Anda menambahkan item baru ke tata letak. Sesuatu seperti di bawah ini:

public void setLayoutFont() {
    Typeface tf = Typeface.createFromAsset(
        getBaseContext().getAssets(), "fonts/BPreplay.otf");
    TextView tv1 = (TextView)findViewById(R.id.tv1);
    tv1.setTypeface(tf);

    TextView tv2 = (TextView)findViewById(R.id.tv2);
    tv2.setTypeface(tf);

    TextView tv3 = (TextView)findViewById(R.id.tv3);
    tv3.setTypeface(tf);
}

EDIT : Jadi saya baru saja menerapkan sesuatu seperti ini sendiri, dan bagaimana saya akhirnya melakukannya adalah membuat fungsi seperti ini:

public static void setLayoutFont(Typeface tf, TextView...params) {
    for (TextView tv : params) {
        tv.setTypeface(tf);
    }
}

Kemudian, cukup gunakan metode ini dari onCreate (), dan teruskan semua TextView yang ingin Anda perbarui:

Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/BPreplay.otf");
//find views by id...
setLayoutFont(tf, tv1, tv2, tv3, tv4, tv5);

EDIT 9/5/12:

Jadi karena ini masih mendapatkan tampilan dan suara, saya ingin menambahkan metode yang jauh lebih baik dan lebih lengkap:

Typeface mFont = Typeface.createFromAsset(getAssets(), "fonts/BPreplay.otf");
ViewGroup root = (ViewGroup)findViewById(R.id.myrootlayout);
setFont(root, mFont);

/*
 * Sets the font on all TextViews in the ViewGroup. Searches
 * recursively for all inner ViewGroups as well. Just add a
 * check for any other views you want to set as well (EditText,
 * etc.)
 */
public void setFont(ViewGroup group, Typeface font) {
    int count = group.getChildCount();
    View v;
    for(int i = 0; i < count; i++) {
        v = group.getChildAt(i);
        if(v instanceof TextView || v instanceof Button /*etc.*/)
            ((TextView)v).setTypeface(font);
        else if(v instanceof ViewGroup)
            setFont((ViewGroup)v, font);
    }
}

Jika Anda meneruskannya ke root layout Anda, itu akan secara rekursif memeriksa TextViewatau Buttonmelihat (atau orang lain yang Anda tambahkan ke pernyataan if) di dalam tata letak itu, dan menyetel font tanpa Anda harus menentukannya dengan ID. Ini tentu saja dengan asumsi Anda ingin mengatur font ke setiap tampilan.

Kevin Coppock
sumber
1
Saya tidak melihat perbedaan apa pun dalam kode Anda dan kode saya kecuali saya menggunakan metode sebagai metode pabrik untuk seluruh aplikasi dan kode Anda sepertinya ditulis untuk satu aktivitas. PS sungguh aneh untuk menambahkan satu objek lagi untuk textView hanya baca hanya untuk mengubah font. Di Luar Topik: Android harus benar-benar memperkenalkan mekanisme untuk mengambil font dari folder assests dan dimasukkan ke dalam R sehingga dapat diubah waktu desain)
Prasham
1
Saya kira secara realistis tidak ada perbedaan besar selain Anda tidak akan membuat Typeface berulang kali. Ide Varun hanya menggunakan jenis huruf statis akan melakukan hal yang sama.
Kevin Coppock
1
Haruskah baris terakhir kode contoh Anda adalah setLayoutFont (tf, tv1, tv2, tv3, tv4, tv5); daripada setTypeface (tf, tv1, tv2, tv3, tv4, tv5) ;?
Kyle Clegg
1
Tidak harus Anda recycleyang TypedArray values?
CorayThan
1
Jika menggunakan Gradle, namespace kustom harusxmlns:custom="http://schemas.android.com/apk/res-auto"
Jabari
93

Ada cara yang cukup mudah untuk melakukan ini melalui XML. Anda hanya perlu membuat widget Anda sendiri yang memperluas TextView.

Pertama, buat file dalam res / values ​​/ attrs.xml dengan konten berikut:

<resources>
    <declare-styleable name="TypefacedTextView">
        <attr name="typeface" format="string" />
    </declare-styleable>
</resources>

Setelah itu, buat widget khusus Anda:

package your.package.widget;

public class TypefacedTextView extends TextView {

    public TypefacedTextView(Context context, AttributeSet attrs) {
        super(context, attrs);

        //Typeface.createFromAsset doesn't work in the layout editor. Skipping...
        if (isInEditMode()) {
            return;
        }

        TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.TypefacedTextView);
        String fontName = styledAttrs.getString(R.styleable.TypefacedTextView_typeface);
        styledAttrs.recycle();

        if (fontName != null) {
            Typeface typeface = Typeface.createFromAsset(context.getAssets(), fontName);
            setTypeface(typeface);
        }
    }

}

Seperti yang Anda lihat, kode di atas akan membaca font di dalam aset / folder. Untuk contoh ini, saya mengasumsikan bahwa ada file bernama "custom.ttf" di folder aset. Terakhir, gunakan widget di XML:

<your.package.widget.TypefacedTextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:your_namespace="http://schemas.android.com/apk/res/your.package"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Custom fonts in XML are easy"
    android:textColor="#FFF"
    android:textSize="14dip"
    your_namespace:typeface="custom.ttf" />

Catatan: Anda tidak akan dapat melihat font khusus Anda di editor tata letak Eclipse. Inilah mengapa saya memberi isInEditMode()cek. Tetapi jika Anda menjalankan aplikasi Anda, font khusus akan berfungsi dengan baik.

Semoga membantu!

leocadiotine
sumber
Saya tidak mencoba ini, tetapi saya membuat kontrol kustom dengan memperluas TextViewkelas; atur typefacedi dalamnya dan gunakan kontrol khusus dalam tata letak seperti yang biasa kita lakukan & itu bekerja untuk saya ... Sederhana saja, bahwa yang di atas ...
Mahendra Liya
1
Saya melakukan apa yang Anda katakan. Satu-satunya perbedaan adalah saya membuat komponen ini dapat digunakan kembali, karena pertanyaannya menanyakan bagaimana melakukan ini melalui XML. Memang ada cara untuk melakukan ini melalui XML dan itulah cara melakukannya :)
leocadiotine
Kode yang sangat mudah diintegrasikan. Ini bekerja untuk saya. Terima kasih.
Durai
1
Yang ini harus menjadi jawaban yang diterima. Ditulis dengan bagus. Terima kasih!
Reaz Murshed
1
Luar biasa, @DominikSuszczewicz! Bisakah Anda membagikan kode sehingga saya dapat memperbarui jawabannya?
leocadiotine
15

Contoh TextView dengan jenis huruf roboto:

attr.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

<declare-styleable name="RobotoTextView">
    <attr name="typeface"/>
</declare-styleable>

<attr name="typeface" format="enum">
    <enum name="roboto_thin" value="0"/>
    <enum name="roboto_thin_italic" value="1"/>
    <enum name="roboto_light" value="2"/>
    <enum name="roboto_light_italic" value="3"/>
    <enum name="roboto_regular" value="4"/>
    <enum name="roboto_italic" value="5"/>
    <enum name="roboto_medium" value="6"/>
    <enum name="roboto_medium_italic" value="7"/>
    <enum name="roboto_bold" value="8"/>
    <enum name="roboto_bold_italic" value="9"/>
    <enum name="roboto_black" value="10"/>
    <enum name="roboto_black_italic" value="11"/>
    <enum name="roboto_condensed" value="12"/>
    <enum name="roboto_condensed_italic" value="13"/>
    <enum name="roboto_condensed_bold" value="14"/>
    <enum name="roboto_condensed_bold_italic" value="15"/>
</attr>

</resources>

RobotoTextView.java:

public class RobotoTextView extends TextView {

/*
 * Permissible values ​​for the "typeface" attribute.
 */
private final static int ROBOTO_THIN = 0;
private final static int ROBOTO_THIN_ITALIC = 1;
private final static int ROBOTO_LIGHT = 2;
private final static int ROBOTO_LIGHT_ITALIC = 3;
private final static int ROBOTO_REGULAR = 4;
private final static int ROBOTO_ITALIC = 5;
private final static int ROBOTO_MEDIUM = 6;
private final static int ROBOTO_MEDIUM_ITALIC = 7;
private final static int ROBOTO_BOLD = 8;
private final static int ROBOTO_BOLD_ITALIC = 9;
private final static int ROBOTO_BLACK = 10;
private final static int ROBOTO_BLACK_ITALIC = 11;
private final static int ROBOTO_CONDENSED = 12;
private final static int ROBOTO_CONDENSED_ITALIC = 13;
private final static int ROBOTO_CONDENSED_BOLD = 14;
private final static int ROBOTO_CONDENSED_BOLD_ITALIC = 15;
/**
 * List of created typefaces for later reused.
 */
private final static SparseArray<Typeface> mTypefaces = new SparseArray<Typeface>(16);

/**
 * Simple constructor to use when creating a view from code.
 *
 * @param context The Context the view is running in, through which it can
 *                access the current theme, resources, etc.
 */
public RobotoTextView(Context context) {
    super(context);
}

/**
 * Constructor that is called when inflating a view from XML. This is called
 * when a view is being constructed from an XML file, supplying attributes
 * that were specified in the XML file. This version uses a default style of
 * 0, so the only attribute values applied are those in the Context's Theme
 * and the given AttributeSet.
 * <p/>
 * <p/>
 * The method onFinishInflate() will be called after all children have been
 * added.
 *
 * @param context The Context the view is running in, through which it can
 *                access the current theme, resources, etc.
 * @param attrs   The attributes of the XML tag that is inflating the view.
 * @see #RobotoTextView(Context, AttributeSet, int)
 */
public RobotoTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    parseAttributes(context, attrs);
}

/**
 * Perform inflation from XML and apply a class-specific base style. This
 * constructor of View allows subclasses to use their own base style when
 * they are inflating.
 *
 * @param context  The Context the view is running in, through which it can
 *                 access the current theme, resources, etc.
 * @param attrs    The attributes of the XML tag that is inflating the view.
 * @param defStyle The default style to apply to this view. If 0, no style
 *                 will be applied (beyond what is included in the theme). This may
 *                 either be an attribute resource, whose value will be retrieved
 *                 from the current theme, or an explicit style resource.
 * @see #RobotoTextView(Context, AttributeSet)
 */
public RobotoTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    parseAttributes(context, attrs);
}

/**
 * Parse the attributes.
 *
 * @param context The Context the view is running in, through which it can access the current theme, resources, etc.
 * @param attrs   The attributes of the XML tag that is inflating the view.
 */
private void parseAttributes(Context context, AttributeSet attrs) {
    TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.RobotoTextView);

    int typefaceValue = values.getInt(R.styleable.RobotoTextView_typeface, 0);
    values.recycle();

    setTypeface(obtaintTypeface(context, typefaceValue));
}

/**
 * Obtain typeface.
 *
 * @param context       The Context the view is running in, through which it can
 *                      access the current theme, resources, etc.
 * @param typefaceValue values ​​for the "typeface" attribute
 * @return Roboto {@link Typeface}
 * @throws IllegalArgumentException if unknown `typeface` attribute value.
 */
private Typeface obtaintTypeface(Context context, int typefaceValue) throws IllegalArgumentException {
    Typeface typeface = mTypefaces.get(typefaceValue);
    if (typeface == null) {
        typeface = createTypeface(context, typefaceValue);
        mTypefaces.put(typefaceValue, typeface);
    }
    return typeface;
}

/**
 * Create typeface from assets.
 *
 * @param context       The Context the view is running in, through which it can
 *                      access the current theme, resources, etc.
 * @param typefaceValue values ​​for the "typeface" attribute
 * @return Roboto {@link Typeface}
 * @throws IllegalArgumentException if unknown `typeface` attribute value.
 */
private Typeface createTypeface(Context context, int typefaceValue) throws IllegalArgumentException {
    Typeface typeface;
    switch (typefaceValue) {
        case ROBOTO_THIN:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Thin.ttf");
            break;
        case ROBOTO_THIN_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-ThinItalic.ttf");
            break;
        case ROBOTO_LIGHT:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Light.ttf");
            break;
        case ROBOTO_LIGHT_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-LightItalic.ttf");
            break;
        case ROBOTO_REGULAR:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Regular.ttf");
            break;
        case ROBOTO_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Italic.ttf");
            break;
        case ROBOTO_MEDIUM:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Medium.ttf");
            break;
        case ROBOTO_MEDIUM_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-MediumItalic.ttf");
            break;
        case ROBOTO_BOLD:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Bold.ttf");
            break;
        case ROBOTO_BOLD_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldItalic.ttf");
            break;
        case ROBOTO_BLACK:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Black.ttf");
            break;
        case ROBOTO_BLACK_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BlackItalic.ttf");
            break;
        case ROBOTO_CONDENSED:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Condensed.ttf");
            break;
        case ROBOTO_CONDENSED_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-CondensedItalic.ttf");
            break;
        case ROBOTO_CONDENSED_BOLD:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldCondensed.ttf");
            break;
        case ROBOTO_CONDENSED_BOLD_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldCondensedItalic.ttf");
            break;
        default:
            throw new IllegalArgumentException("Unknown `typeface` attribute value " + typefaceValue);
    }
    return typeface;
}

}

Contoh penggunaan:

<your.package.widget.RobotoTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:typeface="roboto_thin"
                android:textSize="22sp"
                android:text="Roboto Thin"/>

Sumber: Font Roboto & Noto

e. shishkin
sumber
ada cara untuk menggunakan solusi ini namun tanpa memperbaiki id font di kelas java? mungkin membaca kolom terakhir ini dari enum attrs .. private final static int ROBOTO_THIN = 0; private final static int ROBOTO_THIN_ITALIC = 1; private final static int ROBOTO_LIGHT = 2; ...
Arthur Melo
3

Sudah terlambat tetapi saya membantu yang lain
saya telah membuat CustomTextView yang memiliki atribut yang disebut typeFace dan itu menangani masalah kebocoran memori dengan pemuatan jenis huruf tanpa caching

Pertama Fontskelas yang memuat font dari aset untuk satu kali saja

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

import java.util.Hashtable;

/**
 * Created by tonyhaddad on 7/19/15.
 */
public class Fonts {
    private Context context;

    public Fonts(Context context) {
        this.context = context;
    }
    private static Hashtable<String, Typeface> sTypeFaces = new Hashtable<String, Typeface>(
            4);
    public static Typeface getTypeFace(Context context, String fileName) {
        Typeface tempTypeface = sTypeFaces.get(fileName);

        if (tempTypeface == null) {
            String fontPath=null;
            if(fileName=="metabold")
                fontPath ="fonts/Meta-Bold.ttf";

            else if(fileName=="metanormal")
                fontPath="fonts/Meta-Normal.ttf";
            else if(fileName=="gsligh")
                fontPath="fonts/gesslight.ttf";
            else if(fileName=="bold")
                fontPath="fonts/Lato-Bold.ttf";
            else if(fileName=="rcr")
                fontPath="fonts/RobotoCondensed-Regular.ttf";

            else if(fileName=="mpr")
                fontPath="fonts/MyriadPro-Regular.otf";
            else if(fileName=="rr")
                fontPath="fonts/Roboto-Regular.ttf";

            tempTypeface = Typeface.createFromAsset(context.getAssets(), fontPath);
            sTypeFaces.put(fileName, tempTypeface);
        }

        return tempTypeface;
    }
}

maka Anda perlu menambahkan atribut khusus di attrs.xml tambahkan ini

<declare-styleable name="CustomFontTextView">
        <attr name="typeFace" format="string" />

    </declare-styleable>

lalu kelas khusus

 package package_name;

/**
 * Created by tonyhaddad on 8/26/15.
 */

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

import package_name.R;

public class CustomFontTextView extends TextView {

    String typeFace;


    public CustomFontTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        if (isInEditMode()) {
            return;
        }
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CustomFontTextView,
                0, 0);
        try {
            typeFace = a.getString(0);
        } finally {
            a.recycle();
        }

        if(typeFace!=null && !typeFace.equalsIgnoreCase(""))
        {
            Typeface tf = Fonts.getTypeFace(context, typeFace);
            setTypeface(tf);
        }
        init();
    }

    public CustomFontTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        if (isInEditMode()) {
            return;
        }
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CustomFontTextView,
                0, 0);
        try {
            typeFace = a.getString(0);
        } finally {
            a.recycle();
        }

        if(typeFace!=null && !typeFace.equalsIgnoreCase(""))
        {
            Typeface tf = Fonts.getTypeFace(context, typeFace);
            setTypeface(tf);
        }

        init();
    }

    public CustomFontTextView(Context context) {
        super(context);



        if(typeFace!=null && !typeFace.equalsIgnoreCase(""))
        {
            Typeface tf = Fonts.getTypeFace(context, typeFace);
            setTypeface(tf);
        }
        init();
    }


    private void init() {

    }

    public String getTypeFace() {
        return typeFace;
    }

    public void setTypeFace(String typeFace) {
        this.typeFace = typeFace;
        invalidate();
        requestLayout();
    }
}

dan terakhir tambahkan tampilan teks

  <package_name.CustomFontTextView
            xmlns:custom="http://schemas.android.com/apk/res-auto/package_name"
            android:id="@+id/txt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="41dp"
            android:gravity="center_vertical"
            android:text="text"
            android:textColor="#000"
            android:textSize="23sp"
            custom:typeFace="metanormal"/>

dan Anda dapat mengubah font secara progrmaticlly dengan metode setTypeFace
juga Anda dapat memindahkan namespace kustom ke tata letak induk jika Anda ingin menggunakan lebih dari satu dari tampilan ini

Selamat Coding :)

Antwan
sumber
jawaban stratight sederhana.
eyadMhanna
2

Metode di bawah ini, memanggil onCreate () dan meneruskan ViewGroup terluar Anda, akan bekerja untuk semua hal kecuali teks yang dibuat secara dinamis (mis. Daftar dinamis, peringatan, dll.). Cara mudah untuk mendapatkan ViewGroup terluar adalah dengan menggunakan getRootView di salah satu tampilan Anda.

public void onCreate(Bundle savedInstanceState){
    //onCreate code...
    EditText text = (EditText) findViewById(R.id.editText1);
    setTypeFaceForViewGroup((ViewGroup) text.getRootView());
}

private void setTypeFaceForViewGroup(ViewGroup vg){

    for (int i = 0; i < vg.getChildCount(); i++) {

            if (vg.getChildAt(i) instanceof ViewGroup)
                setTypeFaceForViewGroup((ViewGroup) vg.getChildAt(i));

            else if (vg.getChildAt(i) instanceof TextView)
                ((TextView) vg.getChildAt(i)).setTypeface(Typeface.createFromAsset(getAssets(), "fonts/Your_Font.ttf"));

    }

}

Ini juga harus berfungsi untuk konten dinamis, Anda hanya perlu menyebutnya, meneruskan apa pun yang Anda buat, tepat setelah Anda membuatnya (saya belum menguji ini).

Untuk menghemat memori, Anda mungkin ingin membuat jenis huruf menjadi variabel statis, daripada membuat yang baru setiap kali loop berjalan seperti yang saya lakukan di sini.

Chris
sumber
Saya tidak merekomendasikan solusi ini, karena Anda membuat contoh baru dengan font yang sama untuk setiap elemen yang ingin Anda terapkan. Ini dapat menyebabkan masalah memori.
flawyte
Itu tercakup dalam catatan saya di bagian akhir.
Chris
2

Jika Anda mencari solusi programatik yang lebih umum, saya membuat kelas statis yang dapat digunakan untuk mengatur Jenis huruf dari seluruh tampilan (Activity UI). Perhatikan bahwa saya bekerja dengan Mono (C #) tetapi Anda dapat menerapkannya dengan mudah menggunakan Java.

Anda dapat memberikan kelas ini tata letak atau tampilan tertentu yang ingin Anda sesuaikan. Jika Anda ingin menjadi super efisien, Anda dapat menerapkannya menggunakan pola Singleton.

public static class AndroidTypefaceUtility 
{
    static AndroidTypefaceUtility()
    {
    }
    //Refer to the code block beneath this one, to see how to create a typeface.
    public static void SetTypefaceOfView(View view, Typeface customTypeface)
    {
    if (customTypeface != null && view != null)
    {
            try
            {
                if (view is TextView)
                    (view as TextView).Typeface = customTypeface;
                else if (view is Button)
                    (view as Button).Typeface = customTypeface;
                else if (view is EditText)
                    (view as EditText).Typeface = customTypeface;
                else if (view is ViewGroup)
                    SetTypefaceOfViewGroup((view as ViewGroup), customTypeface);
                else
                    Console.Error.WriteLine("AndroidTypefaceUtility: {0} is type of {1} and does not have a typeface property", view.Id, typeof(View));
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine("AndroidTypefaceUtility threw:\n{0}\n{1}", ex.GetType(), ex.StackTrace);
                    throw ex;
                }
            }
            else
            {
                Console.Error.WriteLine("AndroidTypefaceUtility: customTypeface / view parameter should not be null");
            }
        }

        public static void SetTypefaceOfViewGroup(ViewGroup layout, Typeface customTypeface)
        {
            if (customTypeface != null && layout != null)
            {
                for (int i = 0; i < layout.ChildCount; i++)
                {
                    SetTypefaceOfView(layout.GetChildAt(i), customTypeface);
                }
            }
            else
            {
                Console.Error.WriteLine("AndroidTypefaceUtility: customTypeface / layout parameter should not be null");
            }
        }

    }

Dalam aktivitas Anda, Anda perlu membuat objek Typeface. Saya membuat milik saya di OnCreate () menggunakan file .ttf yang ditempatkan di direktori Resources / Assets / saya. Pastikan file tersebut ditandai sebagai Android Asset di propertinya.

protected override void OnCreate(Bundle bundle)
{               
    ...
    LinearLayout rootLayout = (LinearLayout)FindViewById<LinearLayout>(Resource.Id.signInView_LinearLayout);
    Typeface allerTypeface = Typeface.CreateFromAsset(base.Assets,"Aller_Rg.ttf");
    AndroidTypefaceUtility.SetTypefaceOfViewGroup(rootLayout, allerTypeface);
}
JCKortlang
sumber
2

Sayangnya, Android tidak menyediakan cara cepat, mudah, dan bersih yang Anda cari untuk mengubah font untuk seluruh aplikasi Anda. Tetapi baru-baru ini saya telah melihat masalah ini dan membuat beberapa alat yang memungkinkan Anda untuk mengubah font tanpa pengkodean apa pun (Anda dapat melakukan semuanya melalui xml, gaya, dan bahkan tampilan teks). Mereka didasarkan pada solusi serupa seperti yang Anda lihat di jawaban lain di sini, tetapi memungkinkan lebih banyak fleksibilitas. Anda dapat membaca semuanya di blog ini , dan melihat proyek github di sini .

Berikut contoh cara menerapkan alat-alat ini. Masukkan semua file font Anda assets/fonts/. Kemudian, nyatakan font tersebut dalam file xml (misalnya res/xml/fonts.xml) dan muat file ini di awal aplikasi Anda dengan TypefaceManager.initialize(this, R.xml.fonts);(misalnya, di onCreate kelas Aplikasi Anda). File xml terlihat seperti ini:

<?xml version="1.0" encoding="utf-8"?>
<familyset>

    <!-- Some Font. Can be referenced with 'someFont' or 'aspergit' -->
    <family>
        <nameset>
            <name>aspergit</name>
            <name>someFont</name>
        </nameset>
        <fileset>
            <file>Aspergit.ttf</file>
            <file>Aspergit Bold.ttf</file>
            <file>Aspergit Italic.ttf</file>
            <file>Aspergit Bold Italic.ttf</file>
        </fileset>
    </family>

    <!-- Another Font. Can be referenced with 'anotherFont' or 'bodoni' -->
    <family>
        <nameset>
            <name>bodoni</name>
            <name>anotherFont</name>
        </nameset>
        <fileset>
            <file>BodoniFLF-Roman.ttf</file>
            <file>BodoniFLF-Bold.ttf</file>
        </fileset>
    </family>

</familyset>

Sekarang Anda dapat menggunakan font ini dalam gaya atau xml Anda (asalkan Anda menggunakan alat yang saya sebutkan di atas), dengan menggunakan elemen UI khusus com.innovattic.font.FontTextViewdalam tata letak xml Anda. Di bawah ini Anda dapat melihat bagaimana Anda dapat menerapkan font ke semua teks di seluruh aplikasi Anda, hanya dengan mengedit res/values/styles.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">

    <!-- Application theme -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
        <item name="android:textViewStyle">@style/MyTextViewStyle</item>
    </style>

    <!-- Style to use for ALL text views (including FontTextView) -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="MyTextViewStyle" parent="@android:style/Widget.Holo.Light.TextView">
        <item name="android:textAppearance">@style/MyTextAppearance</item>
    </style>

    <!-- Text appearance to use for ALL text views (including FontTextView) -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="MyTextAppearance" parent="@android:style/TextAppearance.Holo">
        <!-- Alternatively, reference this font with the name "aspergit" -->
        <!-- Note that only our own TextView's will use the font attribute -->
        <item name="flFont">someFont</item>
        <item name="android:textStyle">bold|italic</item>
    </style>

    <!-- Alternative style, maybe for some other widget -->
    <style name="StylishFont">
        <item name="flFont">anotherFont</item>
        <item name="android:textStyle">normal</item>
    </style>

</resources>

Dengan menyertai res/layout/layout.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <!-- This text view is styled with the app theme -->
    <com.innovattic.font.FontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This uses my font in bold italic style" />

    <!-- This text view is styled here and overrides the app theme -->
    <com.innovattic.font.FontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:flFont="anotherFont"
        android:textStyle="normal"
        android:text="This uses another font in normal style" />

    <!-- This text view is styled with a style and overrides the app theme -->
    <com.innovattic.font.FontTextView
        style="@style/StylishFont"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This also uses another font in normal style" />

</LinearLayout>

Jangan lupa untuk menerapkan tema di manifes Android Anda.

Jelle Fresen
sumber
2

Saya ingin menambahkan catatan ke solusi hebat dari leocadiotine. Ini sempurna, tetapi ketika menggunakan Custom TextView ini banyak waktu memperlambat aplikasi, karena harus mengakses aset setiap kali textview dibuat. Saya menyarankan untuk menggunakan sesuatu seperti View Holder patterndi Adapters, saya menulis contoh:

public class Fonts {

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

    public static Typeface getTypeface(Context ctx, String fontName) {
        Typeface typeface = typefaces.get(fontName);
        if (typeface == null) {
            typeface = Typeface.createFromAsset(ctx.getAssets(), fontName);
            typefaces.put(fontName, typeface);
        }
        return typeface;
    } 
}

Dengan cara ini aplikasi hanya mengakses aset satu kali per aset, dan menyimpannya dalam memori untuk kebutuhan selanjutnya.

Emaborsa
sumber
0

Saya tidak tahu apakah itu mengubah seluruh aplikasi, tetapi saya telah berhasil mengubah beberapa komponen yang tidak dapat diubah dengan melakukan ini:

Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/Lucida Sans Unicode.ttf");
Typeface.class.getField("DEFAULT").setAccessible(true);
Typeface.class.getField("DEFAULT_BOLD").setAccessible(true);
Typeface.class.getField("DEFAULT").set(null, tf);
Typeface.class.getField("DEFAULT_BOLD").set(null, tf);
Richard
sumber
@richard, saya ingin menyetel font khusus menurut lokal, Sebagai contoh, saya ingin menyetel Arial TTF saat kami menggunakan bahasa Inggris, dan menyetel TTF gothic saat saya menggunakan bahasa Korea loacale
Dwivedi Ji
0

Saya telah menemukan informasi langkah demi langkah di tautan ini, tautan: https://github.com/jaydipumaretiya/CustomTypeface/

Ada banyak cara untuk menggunakan jenis huruf dengan benar di android, Anda harus meletakkan file jenis huruf Anda di folder assets di bawah utama Anda secara langsung dan dapat menggunakannya secara run-time.

Cara termudah lainnya adalah menggunakan pustaka default untuk mengatur jenis huruf di file xml Anda. Saya lebih suka pustaka jenis huruf kustom ini untuk menyetel jenis huruf ke TextView, EditText, Button, CheckBox, RadioButton dan AutoCompleteTextView dan wedget lainnya di android.

Mehul Rakholiya
sumber
Tautan github tidak berfungsi.
Thomas
0

Android 8.0 (API level 26) memperkenalkan fitur baru, Font dalam XML. Anda bisa membuat file fontfamily dan menyetelnya di styles.xml.

Untuk menambahkan font sebagai sumber daya, lakukan langkah-langkah berikut di Android Studio:

1. Klik kanan folder res dan buka New> Android resource directory. Jendela New Resource Directory muncul.

2. Di daftar Resource type, pilih font, lalu klik OK. Catatan: Nama direktori sumber daya harus font.

3. Tambahkan file font Anda di folder font.

Untuk membuat keluarga font, lakukan langkah-langkah berikut:

1. Klik kanan folder font dan buka New> Font resource file. Jendela New Resource File muncul.

2. Masukkan nama file, lalu klik OK. XML sumber daya font baru terbuka di editor.

3. Tutup setiap file font, gaya, dan atribut bobot di elemen. XML berikut mengilustrasikan penambahan atribut terkait font di XML resource font:

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

Menambahkan font ke gaya

Buka styles.xml, dan setel atribut fontFamily ke file font yang ingin Anda akses.

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

Sumber: Font dalam XML

Pengembang Android
sumber