Можно ли установить собственный шрифт для всего приложения?

java android android-fonts

148715 просмотра

25 ответа

29729 Репутация автора

Мне нужно использовать определенный шрифт для всего моего приложения. У меня есть файл .ttf для того же. Можно ли установить его в качестве шрифта по умолчанию при запуске приложения, а затем использовать его в другом месте приложения? Когда установлено, как я могу использовать его в моих макетах XML?

Автор: Samuh Источник Размещён: 26.04.2010 07:58

Ответы (25)


-15 плюса

5 Репутация автора

Да, можно установить шрифт для всего приложения.

Самый простой способ сделать это - упаковать нужный шрифт (ы) в ваше приложение.

Для этого просто создайте ресурс / папку в корне проекта и поместите ваши шрифты (в форме TrueType или TTF) в ресурсы.

Вы можете, например, создать assets / fonts / и поместить туда свои файлы TTF.

public class FontSampler extends Activity {
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
TextView tv=(TextView)findViewById(R.id.custom);

Typeface face=Typeface.createFromAsset(getAssets(), "fonts/HandmadeTypewriter.ttf");
tv.setTypeface(face);
}
}
Автор: Selvakumar Размещён: 27.05.2010 05:52

47 плюса

4810 Репутация автора

Хотя это не будет работать для всего приложения, оно будет работать для действия и может быть повторно использовано для любого другого действия. Я обновил свой код благодаря @ FR073N для поддержки других видов. Я не уверен , о проблемах с Buttons, RadioGroupsи т.д. , потому что эти классы все простираться TextViewтак что они должны работать нормально. Я добавил булево условие для использования отражения, потому что оно кажется очень хакерским и может заметно снизить производительность.

Примечание: как указано, это не будет работать для динамического контента! Для этого можно вызвать этот метод, скажем, методом onCreateViewили getView, но это требует дополнительных усилий.

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

    final int mCount = mContainer.getChildCount();

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

Затем, чтобы использовать его, вы должны сделать что-то вроде этого:

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

Надеюсь, это поможет.

Автор: Tom Размещён: 13.01.2012 05:38

3 плюса

33627 Репутация автора

Я бы предложил расширить TextView и всегда использовать ваш собственный TextView в макетах XML или там, где вам нужен TextView. В вашем пользовательском TextView переопределитеsetTypeface

@Override
public void setTypeface(Typeface tf, int style) {
    //to handle bold, you could also handle italic or other styles here as well
    if (style == 1){
        tf = Typeface.createFromAsset(getContext().getApplicationContext().getAssets(), "MuseoSans700.otf");
    }else{
        tf = Typeface.createFromAsset(getContext().getApplicationContext().getAssets(), "MuseoSans500.otf");
    }
    super.setTypeface(tf, 0);
}
Автор: Sam Dozor Размещён: 07.03.2012 08:27

9 плюса

2390 Репутация автора

Я бы также предложил расширить TextView и другие элементы управления, но было бы лучше рассмотреть возможность установки шрифта в конструкциях.

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

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

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

protected void init() {
    setTypeface(Typeface.createFromAsset(getContext().getAssets(), AppConst.FONT));
}
Автор: Andrey Mischenko Размещён: 09.11.2012 09:41

447 плюса

40942 Репутация автора

Да с отражением. Это работает ( основываясь на этом ответе ):

(Примечание: это обходной путь из-за отсутствия поддержки пользовательских шрифтов, поэтому, если вы хотите изменить эту ситуацию, пожалуйста, отметьте звездочку, чтобы проголосовать за проблему Android ). Примечание: не оставляйте комментарии "Я тоже" по этому вопросу, все, кто смотрел его, получают по электронной почте, когда вы делаете это. Так что просто "звезда", пожалуйста.

import java.lang.reflect.Field;
import android.content.Context;
import android.graphics.Typeface;

public final class FontsOverride {

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

    protected static void replaceFont(String staticTypefaceFieldName,
            final Typeface newTypeface) {
        try {
            final Field staticField = Typeface.class
                    .getDeclaredField(staticTypefaceFieldName);
            staticField.setAccessible(true);
            staticField.set(null, newTypeface);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

Затем вам нужно перегрузить несколько шрифтов по умолчанию, например, в классе приложения :

public final class Application extends android.app.Application {
    @Override
    public void onCreate() {
        super.onCreate();
        FontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf");
        FontsOverride.setDefaultFont(this, "MONOSPACE", "MyFontAsset2.ttf");
        FontsOverride.setDefaultFont(this, "SERIF", "MyFontAsset3.ttf");
        FontsOverride.setDefaultFont(this, "SANS_SERIF", "MyFontAsset4.ttf");
    }
}

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

Тем не менее, я склонен просто переопределить один, скажем "MONOSPACE", затем настроить стиль, чтобы заставить это приложение шрифта шрифта широко:

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

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

API 21 Android 5.0

Я исследовал сообщения в комментариях, что это не работает и кажется несовместимым с темой android:Theme.Material.Light.

Если эта тема не важна для вас, используйте старую тему, например:

<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
    <item name="android:typeface">monospace</item>
</style>
Автор: weston Размещён: 02.06.2013 01:38

2 плюса

995 Репутация автора

Решение Тома прекрасно работает, но работает только с TextView и EditText.

Если вы хотите охватить большинство представлений (RadioGroup, TextView, Checkbox ...), я создал метод, который делает это:

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

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

Этот метод возвращает стиль представления, заданный в XML (полужирный, курсив ...), и применяет их, если они существуют.

Для ListView я всегда создаю адаптер и устанавливаю шрифт внутри getView.

Автор: FR073N Размещён: 16.09.2013 10:49

15 плюса

158 Репутация автора

это очень просто ... 1. Загрузите и поместите свой собственный шрифт в ресурсы. Затем напишите один отдельный класс для представления текста следующим образом: здесь я использовал шрифт futura.

public class CusFntTextView extends TextView {

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

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

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

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

}

и сделайте следующее в xml:

 <com.packagename.CusFntTextView
        android:id="@+id/tvtitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"         
        android:text="Hi Android"           
        android:textAppearance="?android:attr/textAppearanceLarge"
      />
Автор: Palani Размещён: 08.11.2013 06:54

28 плюса

527 Репутация автора

Я хотел бы улучшить ответ Вестона для API 21 Android 5.0.

причина

Согласно API 21 большинство текстовых стилей включают параметр fontFamily, например:

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

Который применяет стандартный шрифт Roboto Regular:

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

Исходный ответ не может применить моноширинный шрифт, потому что android: fontFamily имеет больший приоритет по сравнению с атрибутом android: typeface ( ссылка ). Использование Theme.Holo. * - допустимый обходной путь, потому что внутри нет настроек android: fontFamily.

Решение

Поскольку Android 5.0 помещает системную гарнитуру в статическую переменную Typeface.sSystemFontMap ( reference ), мы можем использовать ту же технику отражения для ее замены:

protected static void replaceFont(String staticTypefaceFieldName,
        final Typeface newTypeface) {
    if (isVersionGreaterOrEqualToLollipop()) {
        Map<String, Typeface> newMap = new HashMap<String, Typeface>();
        newMap.put("sans-serif", newTypeface);
        try {
            final Field staticField = Typeface.class
                    .getDeclaredField("sSystemFontMap");
            staticField.setAccessible(true);
            staticField.set(null, newMap);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    } else {
        try {
            final Field staticField = Typeface.class
                    .getDeclaredField(staticTypefaceFieldName);
            staticField.setAccessible(true);
            staticField.set(null, newTypeface);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
Автор: Roger Huang Размещён: 06.03.2015 02:21

6 плюса

178 Репутация автора

Работаем на Xamarin. Android:

Класс:

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

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

Реализация приложения:

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

        }

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

        }

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

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

Стиль:

<style name="Theme.Storehouse" parent="Theme.Sherlock">
    <item name="android:typeface">monospace</item>
</style>
Автор: Guy Micciche Размещён: 10.03.2015 03:33

4 плюса

2259 Репутация автора

Вы можете установить пользовательские шрифты для каждого макета один за другим, используя всего один вызов функции из каждого макета, передавая его корневой View.First, создавайте подход синглтона для доступа к объекту шрифта, как этот

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

    private Font() {

    }

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

    }

    public void init(Context context) {

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

}

Вы можете определить различные шрифты в вышеприведенном классе. Теперь определите класс Helper для шрифтов, который будет применять шрифты:

   public class FontHelper {

    private static Font font;

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

        font = Font.getInstance(context);

        apply((ViewGroup)parentView);

    }

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

            View view = parentView.getChildAt(i);

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

            if (view instanceof EditText) {

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

            }
            if (view instanceof TextView) {

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

            }

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

        }

    }

}

В приведенном выше коде я применяю шрифты только к textView и EditText, вы можете применять шрифты и к другим элементам представления аналогично. Вам просто нужно передать идентификатор вашей корневой группы View вышеописанному методу применения шрифта. например, ваш макет:

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

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

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

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

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

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

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

</RelativeLayout>

В вышеприведенном макете идентификатор родительского элемента «Основной родитель» теперь позволяет применять шрифт

public class MainActivity extends BaseFragmentActivity {

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

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

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

Ура :)

Автор: Ajji Размещён: 12.03.2015 07:00

0 плюса

146 Репутация автора

Я также хотел бы улучшить ответ Уэстон для API 21 Android 5.0.

У меня была такая же проблема на моем Samsung s5, когда я использовал шрифт DEFAULT. (с другими шрифтами он работает нормально)

Мне удалось заставить его работать, установив гарнитуру (например, "sans") в файлах XML, для каждого Textview или кнопки

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

и в классе MyApplication:

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

Надеюсь, это поможет.

Автор: stevenwood Размещён: 08.04.2015 01:30

2 плюса

706 Репутация автора

Я написал класс, присваивающий гарнитуру для представлений в текущей иерархии представлений и основанный на текущих свойствах гарнитуры (жирный, обычный, вы можете добавить другие стили, если хотите):

public final class TypefaceAssigner {

public final Typeface DEFAULT;
public final Typeface DEFAULT_BOLD;

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

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

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

Теперь во всех фрагментах в onViewCreated или onCreateView, во всех действиях в onCreate и во всех адаптерах представления в getView или newView просто вызовите:

typefaceAssigner.assignTypeface(view);
Автор: Ivan Kravchenko Размещён: 08.05.2015 01:06

8 плюса

417 Репутация автора

Я хотел бы улучшить Weston «s и Роджер Huang » s ответы на более API 21 Android леденец с темой „ Theme.AppCompat “.

Ниже Android 4.4

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

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

Более (равный) API 5.0

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

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

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

И FontsOverride Util файл такой же , как то , что в Weston ответ «s. Я проверил в этих телефонах:

Nexus 5 (Android 5.1 Основная система Android)

ZTE V5 (Android 5.1 CM12.1)

Примечание XIAOMI (Android 4.4 MIUI6)

HUAWEI C8850 (Android 2.3.5 НЕИЗВЕСТНО)

Автор: lovefish Размещён: 28.05.2015 04:54

8 плюса

7377 Репутация автора

Отличное решение можно найти здесь: https://coderwall.com/p/qxxmaa/android-use-a-custom-font-everywhere .

Просто расширьте действия из BaseActivity и напишите эти методы. Также вы должны лучше кэшировать шрифты, как описано здесь: https://stackoverflow.com/a/16902532/2914140 .


После некоторых исследований я написал код, который работает на Samsung Galaxy Tab A (Android 5.0). Использовали код Уэстона и Роджера Хуанга, а также https://stackoverflow.com/a/33236102/2914140 . Также протестирован на Lenovo TAB 2 A10-70L, где он не работает. Я вставил здесь шрифт Comic Sans, чтобы увидеть разницу.

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

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

    private Context context;

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

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

    private void overrideFonts(Map<String, Typeface> typefaces) {
        if (Build.VERSION.SDK_INT == 21) {
            try {
                final Field field = Typeface.class.getDeclaredField("sSystemFontMap");
                field.setAccessible(true);
                Map<String, Typeface> oldFonts = (Map<String, Typeface>) field.get(null);
                if (oldFonts != null) {
                    oldFonts.putAll(typefaces);
                } else {
                    oldFonts = typefaces;
                }
                field.set(null, oldFonts);
                field.setAccessible(false);
            } catch (Exception e) {
                Log.e("TypefaceUtil", "Cannot set custom fonts");
            }
        } else {
            try {
                for (Map.Entry<String, Typeface> entry : typefaces.entrySet()) {
                    final Field staticField = Typeface.class.getDeclaredField(entry.getKey());
                    staticField.setAccessible(true);
                    staticField.set(null, entry.getValue());
                }
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

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

Чтобы запустить код во всем приложении, вы должны написать в некотором классе, таком как Application, следующее:

    new FontsOverride(this).loadFonts();

Создайте папку «шрифты» внутри «ресурсов» и поместите туда нужные шрифты. Простая инструкция может быть найдена здесь: https://stackoverflow.com/a/31697103/2914140 .

Устройство Lenovo также неправильно получает значение гарнитуры. В большинстве случаев он возвращает Typeface.NORMAL, иногда ноль. Даже если TextView выделен жирным шрифтом (в макете XML-файла). Смотрите здесь: TextView isBold всегда возвращает NORMAL . Таким образом, текст на экране всегда написан обычным шрифтом, а не жирным шрифтом или курсивом. Так что я думаю, что это ошибка производителя.

Автор: CoolMind Размещён: 17.11.2015 03:16

64 плюса

1201 Репутация автора

В Android есть отличная библиотека для пользовательских шрифтов: Каллиграфия

Вот пример, как его использовать.

в Gradle вам нужно поместить эту строку в файл build.gradle вашего приложения:

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

а затем создайте класс, который расширяет Applicationи напишите этот код:

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
                        .setDefaultFontPath("your font path")
                        .setFontAttrId(R.attr.fontPath)
                        .build()
        );
    }
} 

и в классе действия поместите этот метод перед onCreate:

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

и последнее, что ваш файл манифеста должен выглядеть следующим образом:

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

и это изменит всю активность на ваш шрифт! это просто и чисто!

Автор: Shia G Размещён: 02.12.2015 06:08

34 плюса

4670 Репутация автора

В итоге:

Вариант № 1: Используйте отражение, чтобы применить шрифт (объединяя ответ Уэстона и Роджера Хуанга ):

import java.lang.reflect.Field;
import android.content.Context;
import android.graphics.Typeface;

public final class FontsOverride { 

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

    protected static void replaceFont(String staticTypefaceFieldName,final Typeface newTypeface) {
        if (isVersionGreaterOrEqualToLollipop()) {
            Map<String, Typeface> newMap = new HashMap<String, Typeface>();
            newMap.put("sans-serif", newTypeface);
            try {
                final Field staticField = Typeface.class.getDeclaredField("sSystemFontMap");
                staticField.setAccessible(true);
                staticField.set(null, newMap);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        } else {
            try {
                final Field staticField = Typeface.class.getDeclaredField(staticTypefaceFieldName);
                staticField.setAccessible(true);
                staticField.set(null, newTypeface);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } 
        }
    }

} 

Использование в классе приложения:

public final class Application extends android.app.Application {
    @Override 
    public void onCreate() { 
        super.onCreate(); 
        FontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf");
        FontsOverride.setDefaultFont(this, "MONOSPACE", "MyFontAsset2.ttf");
        FontsOverride.setDefaultFont(this, "SERIF", "MyFontAsset3.ttf");
        FontsOverride.setDefaultFont(this, "SANS_SERIF", "MyFontAsset4.ttf");
    } 
} 

установить стиль, чтобы заставить это приложение шрифта использовать шрифт (на основе lovefish ):

Pre-леденец:

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

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

Леденец (API 21):

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

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

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

Вариант 2. Подкласс каждого вида, где вам нужно настроить шрифт, т.е. ListView, EditTextView, Button и т. Д. ( Ответ Палани ):

public class CustomFontView extends TextView {

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

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

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

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

Вариант 3. Реализуйте View Crawler, который просматривает иерархию представлений вашего текущего экрана:

Вариант № 1 ( ответ Тома ):

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

    final int mCount = mContainer.getChildCount();

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

Использование :

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

Вариант № 2: https://coderwall.com/p/qxxmaa/android-use-a-custom-font-everywhere .

Вариант № 4: Используйте сторонний Lib под названием Каллиграфия .

Лично я бы порекомендовал вариант № 4, так как он избавляет от многих головных болей.

Автор: Phileo99 Размещён: 24.03.2016 05:21

0 плюса

426 Репутация автора

Это решение не работает правильно в некоторых ситуациях.
Итак, я расширяю это:

FontsReplacer.java

public class MyApplication extends Application {

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

}

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

Автор: Igor Размещён: 03.06.2016 01:17

0 плюса

410 Репутация автора

Каллиграфия работает довольно хорошо, но она мне не подходит, поскольку она не поддерживает разные веса (полужирный, курсив и т. Д.) Для семейства шрифтов.

Поэтому я попробовал Fontain , который позволяет вам определять собственные представления и применять их к семействам пользовательских шрифтов.

чтобы использовать Fontain, вы должны добавить в свой модуль приложения build.gradle следующее:

compile 'com.scopely:fontain:1.0.0'

Затем вместо обычного TextView следует использовать FontTextView

Пример FontTextView с заглавными и жирными буквами:

 <com.scopely.fontain.views.FontTextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/black"
            android:textColor="@android:color/white"
            android:textSize="11dp"
            android:gravity="center"
            android:id="@+id/tv1"
            app:font_family="myCustomFont"
            app:caps_mode="characters"
            app:font_weight="BOLD"/>
Автор: Cris Размещён: 06.10.2016 11:42

0 плюса

376 Репутация автора

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

public class MyButton extends TextView {

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

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

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

    private void init() {

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

    }

}
Автор: The EasyLearn Academy Размещён: 18.10.2016 06:39

6 плюса

2423 Репутация автора

Что касается Android O, теперь это можно определить непосредственно из XML, и моя ошибка теперь закрыта!

Смотрите здесь для деталей

TL; DR:

Сначала вы должны добавить свои шрифты в проект

Во-вторых, вы добавляете семейство шрифтов, например так:

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

Наконец, вы можете использовать шрифт в макете или стиле:

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

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

Наслаждайтесь!

Автор: Sam Размещён: 11.04.2017 07:36

1 плюс

1144 Репутация автора

в API 26 с build.gradle 3.0.0 и выше вы можете создать каталог шрифтов в Res и использовать эту строку в своем стиле

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

для изменения build.gradle используйте это в ваших зависимостях build.gradle

classpath 'com.android.tools.build:gradle:3.0.0'
Автор: Mohammad Hosein Heidari Размещён: 21.11.2017 10:55

1 плюс

2214 Репутация автора

Наконец, Google осознал серьезность этой проблемы (применяя пользовательский шрифт к компонентам пользовательского интерфейса), и они разработали чистое решение для этой проблемы.

Сначала вам нужно выполнить обновление для поддержки библиотеки 26+ (вам также может понадобиться обновить ваш gradle {4.0+}, android studio), затем вы можете создать новую папку ресурсов с именем font. В эту папку вы можете поместить ресурсы шрифта (.tff, ...). Затем вам нужно переопределить приложение по умолчанию их и заставить свой собственный шрифт в него :)

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

Примечание: если вы хотите поддерживать устройства с более старым API, чем 16, вы должны использовать пространство имен приложения вместо Android!

Автор: Mr.Q Размещён: 20.01.2018 09:52

0 плюса

416 Репутация автора

Чтобы изменить семейство шрифтов по умолчанию для TextViews, переопределите textViewStyle в теме вашего приложения.

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

Эта функция была добавлена ​​в Android 26, но перенесена в более старые версии через supportlib.

https://developer.android.com/guide/topics/resources/font-resource.html https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html # с использованием-поддержка Пб

Автор: Siyamed Размещён: 26.01.2018 05:59

0 плюса

1685 Репутация автора

С момента выпуска Android Oreo и его библиотеки поддержки (26.0.0) вы можете сделать это легко. Обратитесь к этому ответу в другом вопросе.

В основном ваш окончательный стиль будет выглядеть так:

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
   <item name="fontFamily">@font/your_font</item> <!-- target android sdk versions < 26 and > 14 -->
</style>
Автор: João Magalhães Размещён: 13.05.2018 09:16

0 плюса

100 Репутация автора

Я нашел смесь библиотеки каллиграфии 3 и поста Coderwall как мой конечный результат.

Автор: Emi Raz Размещён: 12.10.2019 04:14
Вопросы из категории :
32x32