Android: Хочете встановити спеціальні шрифти для цілої програми, а не під час виконання


100

Чи можна встановити будь-який нестандартний шрифт у кожному контролі програми? І не обов’язково час виконання? (тобто з xml, якщо можливо, або лише один раз для цілої програми у файлі JAVA)

Я можу встановити шрифт для одного елемента керування з цього коду.

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

    textView.setTypeface(tf);

}

І проблема з цим кодом полягає в тому, що його слід викликати для кожного контролю. І я хочу викликати цей або будь-який подібний метод один раз, або, якщо можливо, встановити властивість у xml. Це можливо?


6
Можливо, ви можете написати користувальницький елемент керування, розширивши TextView і встановивши шрифт у конструкторі, може бути варіантом. Тоді ви можете використовувати цей елемент керування у всьому додатку замість вашого перегляду тексту. також для збереження пам'яті u може запобігти завантаження ресурсів за допомогою статичного типу шрифту.
Варун

@Varun: ну ця ідея може заощадити мій час, але мені доведеться встановити кожен контроль, а написання користувальницького контролю для кожного буде довшим способом, ніж встановлення часу виконання шрифту, як ви думаєте? (Однак +1 для написання користувальницького контролю)
Prasham

Ви можете написати лише один спеціальний елемент управління, що розширює textView, і єдиною зміною буде встановлення шрифту. Використовуючи керування cusotm у файлах компонування, вам не доведеться вручну робити це у кожний час для кожного перегляду тексту, і ви все одно можете бути впевнені, що ви використовуєте шрифт, який потрібно.
Варун

А як же писати звичай, VIEWа не писати окремо custom text viewта custom button viewокремо? Моя вимога полягає в кожному контролі, і перегляд тексту був лише прикладом. Вибачте, я забув це згадати .. :-(
Прашам

1
Подивіться на satckoverflow питання stackoverflow.com/questions/2711858 / ... це допомагає вам.
Ашвіні

Відповіді:


123

EDIT : Тож минув час, і я хотів би додати те, що, на мою думку, найкращий спосіб зробити це, і через XML не менше!

Отже, спочатку ви хочете створити новий клас, який переосмислює будь-який вид, який ви хочете налаштувати. (наприклад, хочете кнопку з користувацьким шрифтом? Extend Button). Зробимо приклад:

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

Тепер, якщо у вас його немає, додайте документ XML під res/values/attrs.xmlі додайте:

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

Гаразд, тому з цим не вдається повернутися до parseAttributes()методу з попереднього:

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

Тепер ви все готові. Ви можете додати більше атрибутів про що-небудь (ви можете додати ще один для typefaceStyle - жирний, курсивний тощо), але тепер давайте подивимося, як ним користуватися:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/com.yourpackage.name"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <com.yourpackage.name.CustomButton
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click Me!"
        custom:typeface="roboto" />

</LinearLayout>

xmlns:customЛінія дійсно може бути що завгодно, але угода є те , що показано вище. Що важливо, це те, що він унікальний, і саме тому використовується назва пакета. Тепер ви просто використовуєте custom:префікс для своїх атрибутів і android:префікс для атрибутів Android.

Останнє: якщо ви хочете використовувати це у стилі ( res/values/styles.xml), ви не повинні додавати xmlns:customрядок. Просто посилайтеся на ім'я атрибута без префікса:

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

                               (PREVIOUS ANSWER)

Використання користувацького шрифту в Android

Це має допомогти. В основному, у XML це немає, і наскільки я можу сказати, немає більш простого способу зробити це в коді. Ви завжди можете мати метод setLayoutFont (), який створює шрифт один раз, а потім запускає setTypeface () для кожного. Вам потрібно просто оновлювати його кожного разу, коли ви додаєте новий елемент у макет. Щось подібне нижче:

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 : Отже, я просто взявся за те, щоб реалізувати щось подібне сам, і як я в кінцевому підсумку робив це, робив таку функцію, як ця:

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

Потім просто використовуйте цей метод від onCreate () та передайте всі TextView, які ви хочете оновити:

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

РЕДАКЦІЯ 9/5/12:

Оскільки це все ще отримує думки і голоси, я хотів би додати набагато кращий і більш повний метод:

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

Якщо ви передасте йому корінь свого макета, він буде рекурсивно перевіряти наявність TextViewчи Buttonперегляди (або будь-які інші, які ви додаєте до цього, якщо оператор) у межах цього макета, і встановлюватиме шрифт, не вказуючи їх за ідентифікатором. Звичайно, це передбачає, що ви хочете встановити шрифт для кожного перегляду.


1
Я не бачу різниці у вашому коді та моєму коді, за винятком того, що я використовую метод як заводський метод для цілої програми, і ваш код, здається, написаний для однієї діяльності. PS дійсно дивно додати ще один об’єкт для textView лише для читання, щоб змінити шрифт. Off Topic: Android дійсно повинен запровадити механізм вибору шрифту з папки assts і включення його до R, щоб його можна було змінити час дизайну)
Prasham

1
Я думаю, що реально немає великої різниці, окрім того, як ви не створювали б Typeface знову і знову. Ідея Варуна просто використовувати статичний шрифт зробила б те саме.
Кевін Коппок

1
Якщо слід встановити остаточний рядок вашого прикладу кодуLayoutFont (tf, tv1, tv2, tv3, tv4, tv5); а не setTypeface (tf, tv1, tv2, tv3, tv4, tv5) ;?
Кайл Клегг

1
Не варто recycleTypedArray values ?
CorayThan

1
Якщо використовується Gradle, користувацький простір імен повинен бутиxmlns:custom="http://schemas.android.com/apk/res-auto"
Jabari

93

Існує досить простий спосіб зробити це через XML. Вам просто потрібно створити власний віджет, який розширює TextView.

Спочатку створіть файл у res / values ​​/ attrs.xml із наступним вмістом:

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

Після цього створіть власний віджет:

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

}

Як бачите, наведений вище код буде читати шрифт усередині активів / папки. У цьому прикладі я припускаю, що у папці активів є файл під назвою "custom.ttf". Нарешті, використовуйте віджет у 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" />

Примітка. Ви не зможете побачити власний шрифт у редакторі макетів Eclipse. Ось чому я поставив isInEditMode()чек. Але якщо запустити додаток, користувацький шрифт буде працювати як шарм.

Сподіваюся, це допомагає!


Я цього не пробував, але створив спеціальний елемент керування, розширивши TextViewклас; встановіть typefaceу ньому та використовував користувальницький контроль у макеті, як ми зазвичай робимо & він працював для мене ... Однак було просто, що вищезгадане ...
Mahendra Liya

1
Я зробив саме те, що ти сказав. Єдина відмінність полягає в тому, що я зробив цей компонент багаторазовим, тому що в питанні задається питання, як це зробити за допомогою XML. Дійсно є спосіб зробити це через XML, і це спосіб зробити :)
leocadiotine

Дуже простий код для інтеграції. Це працює для мене. Дякую.
Дурай

1
Це має бути прийнятою відповіддю. Чудово написано. Дякую!
Реаз Муршед

1
Amesome, @DominikSuszczewicz! Чи можете ви поділитися кодом, щоб я міг оновити відповідь?
leocadiotine

15

Приклад TextView з шрифтом 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;
}

}

Приклад використання:

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

Ресурси: шрифти Roboto & Noto


Є спосіб використовувати це рішення, однак без фіксації ідентифікаторів шрифтів у класі java? можливо, прочитайте ці заключні поля з enum attrs .. private final static int ROBOTO_THIN = 0; приватний кінцевий статичний int ROBOTO_THIN_ITALIC = 1; приватний кінцевий статичний int ROBOTO_LIGHT = 2; ...
Артур Мело

3

Це вже пізно, але мій він допомагає іншим,
я створив CustomTextView, який має атрибут під назвою typeFace, і це турбота про проблему витоку пам'яті з завантаженням шрифту без кешування

По-перше, Fontsклас, який завантажує шрифти з активів лише один раз

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

то вам потрібно додати спеціальний атрибут у attrs.xml додати це

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

    </declare-styleable>

потім спеціальний клас

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

і, нарешті, додати перегляд тексту

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

і ви можете змінити шрифт прогрматично методом setTypeFace
також ви можете перемістити спеціальний простір імен у батьківський макет, якщо ви хочете використовувати більше одного з цього представлення

Щасливе кодування :)


проста стратична відповідь.
eyadMhanna

2

Наведений нижче метод, закликаний в onCreate () і передав найвіддаленіший ViewGroup, буде працювати для всього, крім тексту, який створюється динамічно (тобто динамічних списків, попереджень тощо). Найпростіший спосіб отримати найбільш віддалений ViewGroup - це використовувати getRootView на будь-якому з ваших переглядів.

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

    }

}

Це повинно працювати і для динамічного контенту, вам просто доведеться викликати його, передаючи все, що ви створили, відразу після того, як ви його створили (я цього не перевіряв).

Щоб зберегти пам'ять, ви, ймовірно, захочете зробити шрифт шрифту статичною змінною, а не створювати новий кожен раз, коли цикл працює так, як у мене тут.


Я не рекомендую це рішення, тому що ви створюєте новий екземпляр того ж шрифту для кожного елемента, до якого потрібно застосувати. Це може спричинити проблеми з пам’яттю.
flawyte

Це висвітлено в моїй записці наприкінці.
Кріс

2

Якщо ви шукаєте більш загальне програмне рішення, я створив статичний клас, який можна використовувати для встановлення Typeface цілого перегляду (UI діяльності). Зауважте, що я працюю з Mono (C #), але ви можете легко реалізувати це за допомогою Java.

Ви можете передати цьому класу макет або певний вигляд, який потрібно налаштувати. Якщо ви хочете бути надзвичайно ефективними, можете реалізувати це, використовуючи шаблон 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");
            }
        }

    }

У своїй діяльності вам потрібно буде створити об’єкт Typeface. Я створюю шахту в OnCreate (), використовуючи файл .ttf, розміщений у моєму каталозі ресурсів / активів /. Переконайтесь, що файл позначений як Android Asset у своїх властивостях.

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

2

На жаль, Android не забезпечує швидкий, простий і чистий спосіб змінити шрифт для всього додатка. Але нещодавно я розглядав це питання і створив кілька інструментів, які дозволяють змінювати шрифт без будь-якого кодування (ви можете це зробити через XML, стилі та навіть види тексту). Вони базуються на подібних рішеннях, як ви бачите в інших відповідях тут, але дозволяють набагато більше гнучкості. Ви можете прочитати все про це в цьому блозі , а подивитися проект github тут .

Ось приклад того, як застосовувати ці інструменти. Помістіть усі файли шрифтів assets/fonts/. Потім задекларуйте ці шрифти у файлі xml (наприклад res/xml/fonts.xml) та завантажте цей файл на початку свого додатка TypefaceManager.initialize(this, R.xml.fonts);(наприклад, у onCreate класу Application). Файл xml виглядає приблизно так:

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

Тепер ви можете використовувати ці шрифти у своєму стилі чи xml (за умови використання інструментів, про які я згадував вище), використовуючи користувацький елемент інтерфейсу com.innovattic.font.FontTextViewу вашому макеті xml. Нижче ви можете побачити, як можна застосувати шрифт до всіх текстів у всій програмі, просто відредагувавши 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>

Із супроводжуючими 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>

Не забудьте застосувати тему у своєму маніфесті Android.


2

Я хотів би додати ноту до чудового рішення leocadiotine. Це ідеально, але при використанні цього користувальницького TextView багато разів уповільнює додаток, оскільки йому доводиться отримувати доступ до ресурсів щоразу, коли створюється перегляд тексту. Я пропоную використовувати щось на зразок View Holder patternв Adapters, я написав приклад:

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

Таким чином додаток отримує доступ до активів лише один раз на актив, і він зберігає їх у пам'яті для подальших потреб.


0

Я не знаю, чи це змінює весь додаток, але мені вдалося змінити деякі компоненти, які інакше не можна було змінити, зробивши це:

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, я хочу встановити спеціальний шрифт відповідно до локалі. Наприклад, я хочу встановити Arial TTF, коли ми використовуємо англійську мову, і встановити готичний TTF, коли я використовую корейський loacale
Dwivedi Ji

0

Я знайшов покрокову інформацію за цим посиланням, посиланням: https://github.com/jaydipumaretiya/CustomTypeface/

Існує багато способів правильно використовувати шрифт в андроїд, ви повинні помістити файл шрифта в папку активів під основним безпосередньо, і ви можете використовувати його під час виконання.

Іншим найпростішим способом є використання бібліотеки за замовчуванням для встановлення шрифту у вашому XML-файлі. Я віддаю перевагу цій спеціальній бібліотеці шрифтів, щоб встановити шрифт TextView, EditText, Button, CheckBox, RadioButton та AutoCompleteTextView та інший клин в android.


Посилання github не працює.
Томас

0

Android 8.0 (API рівень 26) представляє нову функцію, шрифти в XML. Ви можете створити файл шрифтової сім'ї та встановити його у styles.xml.

Щоб додати шрифти як ресурси, виконайте такі дії в студії Android:

1. Клацніть правою кнопкою миші папку res та перейдіть до каталогу New> Android. З'явиться вікно Новий каталог ресурсів.

2. У списку типів ресурсів виберіть шрифт та натисніть кнопку ОК. Примітка. Ім'я каталогу ресурсів має бути шрифтом.

3.Додайте файли шрифтів у папку шрифтів.

Щоб створити сімейство шрифтів, виконайте наступні дії:

1. Клацніть папку шрифту правою кнопкою миші та перейдіть до пункту «Новий> файл ресурсу шрифту». З'явиться вікно Новий файл ресурсу.

2. Введіть ім'я файлу та натисніть кнопку ОК. У редакторі відкриється новий ресурс шрифту XML.

3.Закрийте кожен елемент атрибуту, стилю та ваги шрифту в елементі. Наступний XML ілюструє додавання пов'язаних з шрифтом атрибутів у ресурс шрифту 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/lobster_regular" />
    <font
        android:fontStyle="italic"
        android:fontWeight="400"
        android:font="@font/lobster_italic" />
</font-family>

Додавання шрифтів до стилю

Відкрийте styles.xml та встановіть атрибут fontFamily файлу шрифту, до якого ви хочете отримати доступ.

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

Джерело: Шрифти в XML

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.