324

我在我的应用程序中使用 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>
4

16 回答 16

314

答案是肯定的。

Global Roboto 灯TextViewButton课程:

<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 这样的内置字体,但这就是问题所在。对于自定义字体(例如从资产加载),此方法将不起作用。

编辑 08/13/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必须包含它。

于 2013-05-06T20:55:10.667 回答
186

随着 Android Oreo 的发布,您可以使用支持库来实现这一目标。

  1. 如果您有支持库>= 26.0.0,请检查您的应用程序build.gradle
  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了解更多详细信息。

于 2017-08-31T10:08:07.850 回答
60

要更改您的应用字体,请按照以下步骤操作:

  1. res目录中创建一个新目录并命名它font
  2. 将字体 .ttf/.otf 插入字体文件夹中,确保字体名称为小写字母和仅下划线。
  3. 里面res-> values->styles.xml里面<resources>-><style>添加你的字体<item name="android:fontFamily">@font/font_name</item>

在此处输入图像描述

现在您的所有应用程序文本都应该使用您添加的字体。

于 2019-02-14T17:57:57.993 回答
35

阅读下面的更新

我在嵌入新字体时遇到了同样的问题,最后让它与扩展 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);
    }
}

您必须稍后将 TextView 元素更改为 from to 在每个元素中。如果您在 Eclipse 中使用 UI-Creator,有时他不会正确显示 TextViews。是唯一对我有用的东西......

更新

现在我使用反射来改变整个应用程序中的字体而不扩展 TextViews。看看这个 SO 帖子

更新 2

从 API 级别 26 开始并在“支持库”中可用,您可以使用

android:fontFamily="@font/embeddedfont"

更多信息:XML 中的字体

于 2013-05-06T20:14:27.447 回答
15

在你的 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”更改为您自己的字体名称..

于 2019-10-24T13:21:24.160 回答
6

只需使用这个库在你的成绩文件中编译它

complie'me.anwarshahriar:calligrapher:1.0'

并在主活动的 onCreate 方法中使用它

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

这是最优雅的超快速方式。

于 2017-08-24T03:15:22.603 回答
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");
    }
}

在您的所有活动中,在 setContentView 之后将当前 ViewGroup 传递给它并完成:

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

对于片段,你可以做类似的事情。

于 2016-04-25T10:19:07.860 回答
5

在 Android Studio 中很容易做到。

  1. 在这种方法中,您需要验证您的minsdkveriosn. 它必须需要minsdkversion >=16

前任:

  1. 在“res”文件夹中创建“font”文件夹。在 android studio 中新建 > 文件夹 > 字体文件夹。

见图片:

  1. 将您的字体文件上传到该字体文件夹。

前任:

  1. 在您的 style.xml 文件中,在“基本应用程序主题”中的样式下添加此行。

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

前任:

于 2021-05-30T02:48:57.420 回答
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 及更高版本的早期版本检查完整示例

于 2015-10-20T12:00:58.587 回答
2

这适用于我的项目,来源https://gist.github.com/artem-zinnatullin/7749076

在 Asset Folder 中创建字体目录,然后将自定义字体复制到字体目录,例如我使用的是 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>

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>

最后,在Activity或Fragment onCreate调用TypefaceUtil.java

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TypefaceUtil.overrideFont(getContext(), "SERIF", "fonts/trebuchet.ttf");
    }
于 2019-02-12T04:46:16.873 回答
1

Android 没有提供太多支持在整个应用程序中应用字体的方式(请参阅此问题)。您有 4 个选项来设置整个应用程序的字体:

  • 选项1:应用反射来改变系统字体
  • 选项 2:为需要自定义字体的每个 View 创建自定义 View 类并将其子类化
  • 选项3:实现一个遍历当前屏幕的视图层次结构的视图爬虫
  • 选项 4:使用 3rd 方库。

可以在此处找到这些选项的详细信息。

于 2016-03-24T17:26:45.783 回答
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) { }
    }
}
于 2016-10-08T13:15:38.347 回答
0

这是我们的做法:

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);
}
于 2020-09-23T06:50:07.103 回答
0

只需将应用程序的字体设置为、normal或(而不是自定义字体!),您可以这样做。sansserifmonospace

定义主题并将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>

安卓参考

于 2016-11-03T06:57:24.253 回答
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" />
于 2017-05-29T13:03:57.227 回答
-7

答案是否定的,你不能。请参阅是否可以为整个应用程序设置自定义字体? 了解更多信息。

有一些解决方法,但是“这里只有一行代码,我所有的字体都将是这个而不是那个”。

(为此我感谢谷歌和苹果)。自定义字体占有一席之地,但让它们易于在应用程序范围内替换,将创建一个完整的Comic Sans应用程序世界)

于 2013-05-06T20:21:05.503 回答