Як встановити сімейство шрифтів за замовчуванням для всього додатка Android


282

Я використовую легкий шрифт Roboto у своєму додатку. Щоб встановити шрифт, я повинен додати android:fontFamily="sans-serif-light"кожен перегляд. Чи є спосіб оголосити шрифт Roboto як сімейство шрифтів за замовчуванням для всього додатка? Я намагався так, але, схоже, не вийшло.

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

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

2
Це може допомогти вам: stackoverflow.com/a/16883281/1329733
Яків R

2
Тепер ви можете вказати спеціальні шрифти прямо з XML в android studio 3.0 developer.android.com/guide/topics/ui/look-and-feel/…
Сім

Відповіді:


289

Відповідь - так.

Глобальне світло Roboto для TextViewта Buttonзанять:

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:textViewStyle">@style/RobotoTextViewStyle</item>
    <item name="android:buttonStyle">@style/RobotoButtonStyle</item>
</style>

<style name="RobotoTextViewStyle" parent="android:Widget.TextView">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

<style name="RobotoButtonStyle" parent="android:Widget.Holo.Button">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

Просто виберіть потрібний стиль із списку themes.xml , а потім створіть свій власний стиль на основі оригінального. В кінці застосуйте стиль як тему програми.

<application
    android:theme="@style/AppTheme" >
</application>

Він працюватиме лише із вбудованими шрифтами, як Roboto, але це було питання. Для спеціальних шрифтів (завантажених, наприклад, з активів) цей метод не працюватиме.

РЕДАКЦІЯ 13.08.15

Якщо ви використовуєте теми AppCompat, не забудьте видалити android:префікс. Наприклад:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:textViewStyle">@style/RobotoTextViewStyle</item>
    <item name="buttonStyle">@style/RobotoButtonStyle</item>
</style>

Зверніть увагу, що префікс buttonStyleне містить android:, але textViewStyleповинен містити його.


4
Звідки ви взяли sans-serif-lightцінність? Чи є fontFamilyдесь список дійсних значень ? Я переглядав документи, а також файли теми та стилів у джерелі Android, і нічого не можу знайти.
Крістофер Перрі

34
це можливо лише для рівня 16 API. Ім'я "android: fontFamily" існує лише на рівні 16 або вище .. Чи існує спосіб це зробити, наприклад, для API 14?
Лоренцо Барбаглі

3
@LorenzoBarbagli, ви можете перевірити каліграфію
Brais Gabin

10
Що робити, якщо у мене є власний шрифт?
Rohit Tigga

2
так ,, я також хочу додати спеціальний шрифт до всього додатку. Як я можу це зробити ?. Чи потрібно мені замінити TextView і замінити всі TextView, як було запропоновано у першій відповіді
Джон

144

З випуском Android Oreo ви можете використовувати бібліотеку підтримки для досягнення цієї мети.

  1. Перевірте у своєму додатку build.gradle, чи є у вас підтримка бібліотеки > = 26.0.0
  2. Додайте папку " шрифт " у папку з ресурсами та додайте туди свої шрифти
  3. Позначте сімейство шрифтів за замовчуванням у головному стилі програми:

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
       <item name="android:fontFamily">@font/your_font</item>
       <item name="fontFamily">@font/your_font</item> <!-- target android sdk versions < 26 and > 14 if theme other than AppCompat -->
    </style>

Перегляньте https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html для отримання більш детальної інформації.


9
Якщо орієнтуватись на API 26+, це має бути прийнятим методом. Використовуючи бібліотеку підтримки , просто видаліть android:префікс
webo80

2
якщо ви використовуєте лише нефіксовану версію, це нормально. Префікс просто ігнорується в API <26
webo80

2
Це не встановлює шрифт скрізь ... Наприклад, якщо у вас є стилі, які випливають із цього Base.TextAppearance.AppCompat, він там не використовується.
Ixx

3
@Ixx, як також замінити ці стилі?
Primož Kralj

2
Не забудьте також використовувати AppCompatTextView під час націлювання на api <26
Codelicious

37

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

  1. Всередині resкаталогу створіть новий каталог і зателефонуйте до нього font.
  2. Вставте свій шрифт .ttf / .otf всередину папки шрифтів, переконайтесь, що назва шрифту - це малі літери та лише підкреслення.
  3. Всередині res-> values-> styles.xmlвсередині <resources>-> <style>додайте свій шрифт <item name="android:fontFamily">@font/font_name</item>.

введіть тут опис зображення

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


8
використовуючи власні шрифти, як я можу додати жирний шрифт разом із звичайними шрифтами?
Rajbir Shienh

Це працює лише з рівнем API 26 і вище, що з API 21 і нижче?
zulkarnain shah

34

ЧИТАЙТЕ ОНОВЛЕННЯ ВНУТРІ

У мене була така ж проблема із вставкою нового шрифту, і, нарешті, він змусив його працювати з розширенням TextView і встановленням шрифту для введення всередину.

public class YourTextView extends TextView {

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

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

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

    private void init() {
        Typeface tf = Typeface.createFromAsset(context.getAssets(),
            "fonts/helveticaneue.ttf");
        setTypeface(tf);
    }
}

Надалі ви повинні змінити елементи TextView пізніше на на на кожен елемент. І якщо ви використовуєте UI-Creator в Eclipse, іноді він не показує TextViews правильно. Це було єдине, що працювало для мене ...

ОНОВЛЕННЯ

Сьогодні я використовую відображення для зміни шрифтів у цілому додатку без розширення TextViews. Ознайомтеся з цим повідомленням SO

ОНОВЛЕННЯ 2

Починаючи з рівня 26 API та доступного в «бібліотеці підтримки», яку ви можете використовувати

android:fontFamily="@font/embeddedfont"

Додаткова інформація: Шрифти в XML


25
Це не рішення. Я використовую багато різних поглядів, не тільки TextView. Я хочу один раз встановити шрифт і забути про нього. Крім того, ваш код створює новий об'єкт для кожного TextView. Принаймні оголошуйте поле статичним, щоб один раз завантажити шрифт із активів.
tomrozb

2
... ну, є функція пошуку та заміни, яка справді добре працює в цьому випадку
longi

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

1
я скасував останнє зобов'язання.
longi

1
@tomrozb: D Я щойно зрозумів, що останні швидкі зміни, які я зробив, були через ваші коментарі! оскільки у вас достатньо балів, ви можете оптимізувати приклад коду самостійно. інакше ми все ще поговоримо про цю тему через кілька років, коли вже ніхто не переймається смартфонами;)
longi

8

Додайте цей рядок коду у свій res / value / styles.xml

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

весь стиль буде виглядати так

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:fontFamily">@font/circular_medium</item>
</style>

змініть "circular_medium" на власне ім'я шрифту ..


6

Не кажучи про продуктивність, для користувацького шрифту ви можете мати цикл рекурсивного методу через усі перегляди та встановити шрифт, якщо це TextView:

public class Font {
    public static void setAllTextView(ViewGroup parent) {
        for (int i = parent.getChildCount() - 1; i >= 0; i--) {
            final View child = parent.getChildAt(i);
            if (child instanceof ViewGroup) {
                setAllTextView((ViewGroup) child);
            } else if (child instanceof TextView) {
                ((TextView) child).setTypeface(getFont());
            }
        }
    }

    public static Typeface getFont() {
        return Typeface.createFromAsset(YourApplicationContext.getInstance().getAssets(), "fonts/whateverfont.ttf");
    }
}

У всій своїй діяльності передайте йому поточний ViewGroup після setContentView і це зроблено:

ViewGroup group = (ViewGroup) getWindow().getDecorView().findViewById(android.R.id.content);
Font.setAllTextView(group);

Для фрагменту можна зробити щось подібне.


1
Звучить чудово, але цікаво, як зробити так, щоб він працював у вмісті recilerView?
Srujan Barai

Я просто спробував це. занадто важкий для надання. Уповільнюється, recyclerViewяк пекло.
Srujan Barai

Повністю не рекомендується для будь-якого переліку списків, цей трюк призначений лише для економії часу для статичного перегляду коду.
Аллен Чан

5

Ще один спосіб зробити це для всього додатка - це використання роздумів, заснованих на цій відповіді

public class TypefaceUtil {
    /**
     * Using reflection to override default typefaces
     * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE
     * OVERRIDDEN
     *
     * @param typefaces map of fonts to replace
     */
    public static void overrideFonts(Map<String, Typeface> typefaces) {
        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", "Can not set custom fonts");
        }
    }

    public static Typeface getTypeface(int fontType, Context context) {
        // here you can load the Typeface from asset or use default ones
        switch (fontType) {
            case BOLD:
                return Typeface.create(SANS_SERIF, Typeface.BOLD);
            case ITALIC:
                return Typeface.create(SANS_SERIF, Typeface.ITALIC);
            case BOLD_ITALIC:
                return Typeface.create(SANS_SERIF, Typeface.BOLD_ITALIC);
            case LIGHT:
                return Typeface.create(SANS_SERIF_LIGHT, Typeface.NORMAL);
            case CONDENSED:
                return Typeface.create(SANS_SERIF_CONDENSED, Typeface.NORMAL);
            case THIN:
                return Typeface.create(SANS_SERIF_MEDIUM, Typeface.NORMAL);
            case MEDIUM:
                return Typeface.create(SANS_SERIF_THIN, Typeface.NORMAL);
            case REGULAR:
            default:
                return Typeface.create(SANS_SERIF, Typeface.NORMAL);
        }
    }
}

тоді, коли ви хочете змінити шрифти, ви можете просто зателефонувати за методом і надати йому карту шрифтів наступним чином:

Typeface regular = TypefaceUtil.getTypeface(REGULAR, context);
Typeface light = TypefaceUtil.getTypeface(REGULAR, context);
Typeface condensed = TypefaceUtil.getTypeface(CONDENSED, context);
Typeface thin = TypefaceUtil.getTypeface(THIN, context);
Typeface medium = TypefaceUtil.getTypeface(MEDIUM, context);
Map<String, Typeface> fonts = new HashMap<>();
fonts.put("sans-serif", regular);
fonts.put("sans-serif-light", light);
fonts.put("sans-serif-condensed", condensed);
fonts.put("sans-serif-thin", thin);
fonts.put("sans-serif-medium", medium);
TypefaceUtil.overrideFonts(fonts);

для повної перевірки прикладу

Це працює лише для Android SDK 21 і вище, для більш ранніх версій перевірити повний приклад


5

Просто скористайтеся цією lib, компілюйте її у вашому файлі оцінок

complie'me.anwarshahriar:calligrapher:1.0'

і використовувати його в методі onCreate в основній діяльності

Calligrapher calligrapher = new Calligrapher(this);
calligrapher.setFont(this, "yourCustomFontHere.ttf", true);

Це найелегантніший швидкий спосіб зробити це.


2

Це робота для мого проекту, джерело https://gist.github.com/artem-zinnatullin/7749076

Створіть каталог шрифтів всередині папки Asset, а потім скопіюйте свій власний шрифт у каталог шрифтів, наприклад, я використовую trebuchet.ttf;

Створити клас TypefaceUtil.java;

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

import java.lang.reflect.Field;
public class TypefaceUtil {

    public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) {
        try {
            final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets);

            final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);
            defaultFontTypefaceField.setAccessible(true);
            defaultFontTypefaceField.set(null, customFontTypeface);
        } catch (Exception e) {

        }
    }
}

Редагуйте тему в styles.xml додати нижче

<item name="android:typeface">serif</item>

Приклад у Моїх стилях.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:typeface">serif</item><!-- Add here -->
    </style>


    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:windowFullscreen">true</item>
    </style>
</resources>

Нарешті, в «Активність» або «Фрагмент» створити виклик TypefaceUtil.java

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TypefaceUtil.overrideFont(getContext(), "SERIF", "fonts/trebuchet.ttf");
    }

0

Android не дуже підтримує застосування шрифтів у всьому додатку (див. Цю проблему ). У вас є 4 варіанти встановлення шрифту для всього додатка:

  • Варіант1: застосуйте відображення для зміни шрифту системи
  • Варіант2: Створення та підклас спеціальних класів перегляду для кожного представлення, для якого потрібен спеціальний шрифт
  • Варіант 3: Вкажіть сканер перегляду, який проходить ієрархію подання для поточного екрана
  • Варіант4: Використовуйте сторонню бібліотеку.

Детальну інформацію про ці параметри можна знайти тут .


0

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

public static void setFont(ViewGroup layout)
{
    final int childcount = layout.getChildCount();
    for (int i = 0; i < childcount; i++)
    {
        // Get the view
        View v = layout.getChildAt(i);

        // Apply the font to a possible TextView
        try {
            ((TextView) v).setTypeface(MY_CUSTOM_FONT);
            continue;
        }
        catch (Exception e) { }

        // Apply the font to a possible EditText
        try {
            ((TextView) v).setTypeface(MY_CUSTOM_FONT);
            continue;
        }
        catch (Exception e) { }

        // Recursively cicle into a possible child layout
        try {
            ViewGroup vg = (ViewGroup) v;
            Utility.setFont(vg);
            continue;
        }
        catch (Exception e) { }
    }
}

0

щоб просто набір накреслення додатки до normal, sans, serifабо monospace(Не призначений для користувача шрифт!), ви можете зробити це.

визначте тему та встановіть android:typefaceатрибут для шрифту, який ви хочете використовувати у styles.xml:

<resources>

    <!-- custom normal activity theme -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <!-- other elements -->
        <item name="android:typeface">monospace</item>
    </style>

</resources>

застосувати тему до всього додатку у AndroidManifest.xmlфайлі:

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application
        android:theme="@style/AppTheme" >
    </application>
</manifest>

андроїд посилання


Ви впевнені, що це працює? За словами доктора Android: "Повинно бути одне з таких постійних значень: нормальне, sans, serif, monospace".
tomrozb

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

Привіт @Dave Cruise, це працює лише для монопростору? Я протестував його лише на монопростір ... і більше нічого .... тому я не впевнений ... але згідно документації, він повинен працювати і для "нормальних", "sans" і "serif". . Я думаю, що шрифт є більш загальним, ніж шрифт, тому ми не можемо використовувати його для встановлення шрифту програми на певний шрифт, наприклад "консолі" чи щось.
Ерік

@Eric yea. Я теж не маю уявлення. Монопростір працює як шарм, але не пощастить нормальним, санам чи серифам.
Дейв Круїз

0

Спробуйте цю бібліотеку, її легку та просту у виконанні

https://github.com/sunnag7/FontStyler

<com.sunnag.fontstyler.FontStylerView
              android:textStyle="bold"
              android:text="@string/about_us"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:paddingTop="8dp"
              app:fontName="Lato-Bold"
              android:textSize="18sp"
              android:id="@+id/textView64" />

-7

Відповідь - ні, ви не можете. Див. Чи можливо встановити спеціальний шрифт для всієї програми? для отримання додаткової інформації.

Є обхідні шляхи, але нічого у рядках "одного єдиного рядка коду тут, і всі мої шрифти будуть це замість цього ".

(Я вдячний за це Google-Apple і Apple). Спеціальні шрифти мають місце, але полегшуючи їх замінити на широкі програми, це створило б увесь світ програм Comic Sans )


41
Повністю не згоден з вашим коментарем. Налаштування шрифту в усьому світі має бути тривіальним для виконання, а не те, що вимагає типів обхідних способів. Розробники / дизайнери світу повинні уникати програм "Comic Sans", а не Google / Apple для цього.
LocalPCGuy

4
Консистенція> Фантастичний дизайн.
Мартін Маркончіні

14
Однак послідовність <функціональність. Ми розробляємо додатки, які відображають біблійну іврит. Усі шрифти акцій, що знаходяться на пристроях Android (включаючи останні шрифти Android L), виконують ненормальну роботу по виведенню знаків контиляції (і, з цього приводу, вони виконують посередню роботу на знаках голосних, хоча вони стають кращими). Нам абсолютно необхідно використовувати спеціальний шрифт у всьому нашому додатку, і нам довелося написати занадто багато коду, щоб просто отримати всі необхідні перегляди за його допомогою.
Тед Хопп
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.