简体   繁体   English

如何为整个 Android 应用设置默认字体系列

[英]How to set default font family for entire Android app

I'm using the Roboto light font in my app.我在我的应用程序中使用 Roboto 浅色字体。 To set the font I've to add the android:fontFamily="sans-serif-light" to every view.要设置字体,我必须将android:fontFamily="sans-serif-light"添加到每个视图。 Is there any way to declare the Roboto font as default font family to entire app?有没有办法将 Roboto 字体声明为整个应用程序的默认字体系列? I've tried like this but it didn't seem to work.我试过这样,但似乎没有用。

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

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

The answer is yes.答案是肯定的。

Global Roboto light for TextView and Button classes: TextViewButton类的全局 Roboto 灯:

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

Just select the style you want from list themes.xml , then create your custom style based on the original one.只需从列表Themes.xml中选择您想要的样式,然后根据原始样式创建您的自定义样式。 At the end, apply the style as the theme of the application.最后,将样式应用为应用程序的主题。

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

It will work only with built-in fonts like Roboto, but that was the question.它只适用于像 Roboto 这样的内置字体,但这就是问题所在。 For custom fonts (loaded from assets for example) this method will not work.对于自定义字体(例如从资产加载),此方法将不起作用。

EDIT 08/13/15编辑 08/13/15

If you're using AppCompat themes, remember to remove android: prefix.如果您使用 AppCompat 主题,请记住删除android:前缀。 For example:例如:

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

Note the buttonStyle doesn't contain android: prefix, but textViewStyle must contain it.注意buttonStyle不包含android:前缀,但textViewStyle必须包含它。

With the release of Android Oreo you can use the support library to reach this goal.随着 Android Oreo 的发布,您可以使用支持库来实现这一目标。

  1. Check in your app build.gradle if you have the support library >= 26.0.0如果您有支持库>= 26.0.0 ,请检查您的应用程序build.gradle
  2. Add " font " folder to your resources folder and add your fonts there将“字体”文件夹添加到您的资源文件夹并在那里添加您的字体
  3. Reference your default font family in your app main style:在您的应用主样式中引用您的默认字体系列:

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

Check https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html for more detailed information.查看https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html了解更多详细信息。

To change your app font follow the following steps:要更改您的应用字体,请按照以下步骤操作:

  1. Inside res directory create a new directory and name it font .res目录中创建一个新目录并将其命名为font
  2. Insert your font .ttf/.otf inside the font folder, Make sure the font name is lower case letters and underscore only.将字体 .ttf/.otf 插入字体文件夹中,确保字体名称为小写字母和仅下划线。
  3. Inside res -> values -> styles.xml inside <resources> -> <style> add your font <item name="android:fontFamily">@font/font_name</item> .res -> values -> styles.xml里面<resources> -> <style>添加你的字体<item name="android:fontFamily">@font/font_name</item>

在此处输入图像描述

Now all your app text should be in the font that you add.现在您的所有应用程序文本都应该使用您添加的字体。

READ UPDATES BELOW阅读下面的更新

I had the same issue with embedding a new font and finally got it to work with extending the TextView and set the typefont inside.我在嵌入新字体时遇到了同样的问题,最后让它与扩展 TextView 并在里面设置 typefont 一起工作。

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

You have to change the TextView Elements later to from to in every element.您必须稍后将 TextView 元素更改为 from to 在每个元素中。 And if you use the UI-Creator in Eclipse, sometimes he doesn't show the TextViews right.如果您在 Eclipse 中使用 UI-Creator,有时他不会正确显示 TextViews。 Was the only thing which work for me...是唯一对我有用的东西......

UPDATE更新

Nowadays I'm using reflection to change typefaces in whole application without extending TextViews.现在我使用反射来改变整个应用程序中的字体而不扩展 TextViews。 Check out this SO post 看看这个 SO 帖子

UPDATE 2更新 2

Starting with API Level 26 and available in 'support library' you can use从 API 级别 26 开始并在“支持库”中可用,您可以使用

android:fontFamily="@font/embeddedfont"

Further information: Fonts in XML更多信息: XML 中的字体

Add this line of code in your res/value/styles.xml在你的 res/value/styles.xml 中添加这行代码

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

the entire style will look like that整个风格看起来像这样

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

change "circular_medium" to your own font name..将“circular_medium”更改为您自己的字体名称..

Not talk about performance, for custom font you can have a recursive method loop through all the views and set typeface if it's a TextView:不谈论性能,对于自定义字体,您可以使用递归方法循环遍历所有视图并设置字体(如果它是 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");
    }
}

In all your activity, pass current ViewGroup to it after setContentView and it's done:在您的所有活动中,在 setContentView 之后将当前 ViewGroup 传递给它并完成:

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

For fragment you can do something similar.对于片段,你可以做类似的事情。

It's very very very easy to do in Android Studio.在 Android Studio 中很容易做到。

  1. In this method you need to verify your minsdkveriosn .在这种方法中,您需要验证您的minsdkveriosn It must need minsdkversion >=16它必须需要minsdkversion >=16

前任:

  1. Create "font" folder inside "res" folder.在“res”文件夹中创建“font”文件夹。 In android studio New > Folder > Font Folder.在 android studio 中新建 > 文件夹 > 字体文件夹。

见图片:

  1. Upload your font file to that font folder.将您的字体文件上传到该字体文件夹。

前任:

  1. In you style.xml file, Under style in "Base application theme" add this line.在您的 style.xml 文件中,在“基本应用程序主题”中的样式下添加此行。

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

前任:

More Details: https://coderog.com/community/threads/how-to-set-default-font-family-for-entire-android-app.72/更多详情: https ://coderog.com/community/threads/how-to-set-default-font-family-for-entire-android-app.72/

Another way to do this for the whole app is using reflection based on this answer为整个应用程序执行此操作的另一种方法是使用基于此答案的反射

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

then whenever you want to override the fonts you can just call the method and give it a map of typefaces as follows:然后,每当您想覆盖字体时,您只需调用该方法并为其提供字体映射,如下所示:

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

for full example check完整的示例检查

This only works for Android SDK 21 and above for earlier versions check the full example这仅适用于 Android SDK 21 及更高版本的早期版本检查完整示例

Just use this lib compile it in your grade file只需使用这个库在你的成绩文件中编译它

complie'me.anwarshahriar:calligrapher:1.0'

and use it in the onCreate method in the main activity并在主活动的 onCreate 方法中使用它

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

This is the most elegant super fast way to do that.这是最优雅的超快速方式。

This is work for my project, source https://gist.github.com/artem-zinnatullin/7749076这适用于我的项目,来源https://gist.github.com/artem-zinnatullin/7749076

Create fonts directory inside Asset Folder and then copy your custom font to fonts directory, example I am using trebuchet.ttf;在 Asset Folder 中创建字体目录,然后将自定义字体复制到字体目录,例如我使用的是 trebuchet.ttf;

Create a class TypefaceUtil.java;创建一个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) {

        }
    }
}

Edit theme in styles.xml add below在styles.xml 中编辑主题添加下面

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

Example in My styles.xml My styles.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>

Finally, in Activity or Fragment onCreate call TypefaceUtil.java最后,在Activity或Fragment onCreate调用TypefaceUtil.java

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

Android does not provide much in the way of support for applying fonts across the whole app (see this issue ). Android 没有提供太多支持在整个应用程序中应用字体的方式(请参阅此问题)。 You have 4 options to set the font for the entire app:您有 4 个选项来设置整个应用程序的字体:

  • Option1: Apply reflection to change the system font选项1:应用反射来改变系统字体
  • Option2: Create and subclass custom View classes for each View that needs a custom font选项 2:为需要自定义字体的每个 View 创建自定义 View 类并将其子类化
  • Option3: Implement a View Crawler which traverses the view hierarchy for the current screen选项3:实现一个遍历当前屏幕的视图层次结构的视图爬虫
  • Option4: Use a 3rd party library.选项 4:使用 3rd 方库。

Details of these options can be found here .可以在此处找到这些选项的详细信息。

I know this question is quite old, but I have found a nice solution.我知道这个问题已经很老了,但我找到了一个很好的解决方案。 Basically, you pass a container layout to this function, and it will apply the font to all supported views, and recursively cicle in child layouts:基本上,您将容器布局传递给此函数,它会将字体应用于所有支持的视图,并在子布局中递归循环:

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

to merely set typeface of app to normal , sans , serif or monospace (not to a custom font!), you can do this.只需将应用程序的字体设置为normalsansserifmonospace (而不是自定义字体!),您可以这样做。

define a theme and set the android:typeface attribute to the typeface you want to use in styles.xml :定义主题并将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>

apply the theme to the whole app in the AndroidManifest.xml file:将主题应用于AndroidManifest.xml文件中的整个应用程序:

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

android reference 安卓参考

Try this library, its lightweight and easy to implement试试这个库,它轻量级且易于实现

https://github.com/sunnag7/FontStyler 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" />

This is how we do it:这是我们的做法:

private static void OverrideDefaultFont(string defaultFontNameToOverride, string customFontFileNameInAssets, AssetManager assets)
{
    //Load custom Font from File                
    Typeface customFontTypeface = Typeface.CreateFromAsset(assets, customFontFileNameInAssets);

    //Get Fontface.Default Field by reflection
    Class typeFaceClass = Class.ForName("android.graphics.Typeface");
    Field defaultFontTypefaceField = typeFaceClass.GetField(defaultFontNameToOverride);

    defaultFontTypefaceField.Accessible = true;
    defaultFontTypefaceField.Set(null, customFontTypeface);
}

The answer is no, you can't.答案是否定的,你不能。 See Is it possible to set a custom font for entire of application?请参阅是否可以为整个应用程序设置自定义字体? for more information.了解更多信息。

There are workarounds, but nothing in the lines of "one single line of code here and all my fonts will be this instead of that ".有一些解决方法,但是“这里只有一行代码,我所有的字体都将是这个而不是那个”。

(I kind of thank Google -and Apple- for that). (为此我感谢谷歌和苹果)。 Custom fonts have a place, but making them easy to replace app wide, would have created an entire world of Comic Sans applications)自定义字体占有一席之地,但让它们易于在应用程序范围内替换,将创建一个完整的Comic Sans应用程序世界)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM