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 и установив шрифт в конструкторе, который может быть вариантом. Затем вы можете использовать этот элемент управления во всем приложении вместо вашего текстового представления. также для экономии памяти вы можете предотвратить загрузку ресурсов, используя статический шрифт.
Варун
@Varun: ну, эта идея может сэкономить мое время, но я должен установить каждый элемент управления, и написание пользовательского элемента управления для каждого будет более длительным способом, чем установка времени выполнения шрифта, как вы думаете? (Однако +1 за написание пользовательского контроля)
Prasham
Возможно, вы захотите написать только один настраиваемый элемент управления, расширяющий textView, и единственной модификацией будет установка гарнитуры. Используя элемент управления cusotm в ваших файлах макета, вам не нужно вручную делать это каждый раз для каждого текстового просмотра, и вы все равно можете быть уверены, что используете нужный шрифт.
Варун
Как насчет того, чтобы написать обычай VIEWвместо того, чтобы писать a custom text viewи a по custom button viewотдельности? Мое требование касается каждого элемента управления, и текстовое представление было просто примером. Извините, я забыл об этом упомянуть .. :-(
Prasham
1
Взгляните на вопрос satckoverflow stackoverflow.com/questions/2711858/… он вам поможет.
Ashwini

Ответы:

123

РЕДАКТИРОВАТЬ : Итак, прошло некоторое время, и я хотел бы добавить то, что я считаю лучшим способом сделать это, и не менее, через XML!

Итак, сначала вам нужно создать новый класс, который переопределяет любой View, который вы хотите настроить. (например, хотите кнопку с настраиваемым шрифтом? Расширить 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.

И последнее: если вы хотите использовать это в style ( 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);
}

РЕДАКТИРОВАТЬ : Итак, я просто нашел время для реализации чего-то вроде этого сам, и как я в итоге это сделал, создал такую ​​функцию, как эта:

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представления (или любые другие, которые вы добавляете к этому оператору if) в этом макете и устанавливать шрифт без необходимости указывать их по идентификатору. Это, конечно, предполагает, что вы хотите установить шрифт для каждого представления.

Кевин Коппок
источник
1
Я не вижу никакой разницы в вашем коде и моем коде, за исключением того, что я использую метод как фабричный метод для всего приложения, и ваш код, похоже, написан для одного действия. PS действительно странно добавить еще один объект для textView только для чтения, просто чтобы изменить шрифт. Вне темы: Android действительно должен представить механизм для извлечения шрифта из папки Assests и включения его в R, чтобы его можно было изменить во время разработки)
Prasham
1
Я думаю, что на самом деле нет большой разницы, кроме того, что вы бы не создавали шрифт снова и снова. Идея Варуна об использовании статического шрифта сделала бы то же самое.
Кевин Коппок
1
Если последняя строка вашего примера кода должна быть установлена ​​- LayoutFont (tf, tv1, tv2, tv3, tv4, tv5); а не setTypeface (tf, tv1, tv2, tv3, tv4, tv5) ;?
Кайл Клегг
1
Не должны ли вы ? recycleTypedArray values
CorayThan 09
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);
        }
    }

}

Как видите, приведенный выше код считывает шрифт внутри папки assets /. В этом примере я предполагаю, что в папке с ресурсами есть файл с именем «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в нем и использовал настраиваемый элемент управления в макете, как мы обычно это делаем, и это сработало для меня ... Однако это было просто, что указанное выше ...
Махендра Лия
1
Я сделал именно то, что ты сказал. Единственная разница в том, что я сделал этот компонент многоразовым, потому что вопрос заключается в том, как это сделать через XML. Действительно есть способ сделать это через XML, и это способ сделать это :)
леокадиотин
Очень простой код для интеграции. Меня устраивает. Спасибо.
Дурай
1
Это должен быть принятый ответ. Красиво написано. Спасибо!
Реаз Муршед
1
Амесом, @DominikSuszczewicz! Не могли бы вы поделиться кодом, чтобы я мог обновить ответ?
леокадиотин 01
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
также вы можете переместить пользовательское пространство имен в свой родительский макет, если вы хотите использовать более одного из этого представления

Удачного кодирования :)

Antwan
источник
простой прямолинейный ответ.
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

Если вы ищете более общее программное решение, я создал статический класс, который можно использовать для установки гарнитуры всего представления (Activity 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, расположенный в моем каталоге Resources / Assets /. Убедитесь, что файл помечен как актив Android в его свойствах.

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
источник
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. Это прекрасно, но при использовании этого Custom 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;
    } 
}

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

Emaborsa
источник
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/

Есть много способов правильно использовать гарнитуру в Android, вы должны поместить файл гарнитуры в папку с активами непосредственно под вашим основным шрифтом и можете использовать его во время выполнения.

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

Мехул Рахолия
источник
0

В Android 8.0 (уровень API 26) представлена ​​новая функция - «Шрифты в XML». Вы можете создать файл fontfamily и установить его в styles.xml.

Чтобы добавить шрифты в качестве ресурсов, выполните следующие действия в Android Studio:

1. Щелкните правой кнопкой мыши папку res и выберите «Создать»> «Каталог ресурсов Android». Откроется окно «Новый каталог ресурсов».

2. В списке Тип ресурса выберите шрифт и нажмите OK. Примечание. Имя каталога ресурсов должно быть шрифтом.

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

Разработчик Android
источник