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

tom*_*ozb 256 android android-fonts

我在我的应用程序中使用Roboto light字体.要设置字体,我要添加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>
Run Code Online (Sandbox Code Playgroud)

tom*_*ozb 270

答案是肯定的.

全球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>
Run Code Online (Sandbox Code Playgroud)

只需从列表themes.xml中选择所需的样式,然后根据原始样式创建自定义样式.最后,将样式应用为应用程序的主题.

<application
    android:theme="@style/AppTheme" >
</application>
Run Code Online (Sandbox Code Playgroud)

它只适用于像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>
Run Code Online (Sandbox Code Playgroud)

请注意,buttonStyle它不包含android:前缀,但textViewStyle必须包含前缀.

  • 这只适用于API级别16 ..名称"android:fontFamily"仅存在于16级或更高级别.例如,有没有办法为API 14执行此操作? (33认同)
  • 那么如果我有自定义字体怎么办? (10认同)
  • 你从哪里得到'sans-serif-light`值?某处有'fontFamily`的有效值列表吗?我一直在浏览文档,以及Android源代码中的主题和样式文件,但找不到任何内容. (3认同)
  • @LorenzoBarbagli,你可以查看[书法](https://github.com/chrisjenx/Calligraphy) (3认同)
  • 是的,我还想向整个应用程序添加自定义字体。我怎样才能做到这一点 ?。我是否需要覆盖TextView并替换第一个答案中建议的所有TextView (2认同)

Joã*_*ães 126

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

  1. 检查您的应用程序的build.gradle如果您有支持库> = 26.0.0
  2. 将" font "文件夹添加到资源文件夹并在那里添加字体
  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>
    
    Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请访问https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html.

  • 在定位API 26+时,这应该是可接受的方法.使用_Support Library_时,只需删除`android:`前缀即可 (9认同)
  • @Ixx,如何覆盖这些样式呢? (3认同)
  • 如果仅使用无前缀版本,则可以。带前缀的只是在API &lt;26上将被忽略 (2认同)
  • 这不会在所有地方设置字体...例如,如果您具有从Base.TextAppearance.AppCompat派生的样式,则此处不会使用它。 (2认同)
  • 定位api &lt;26时,请记住还要使用AppCompatTextView (2认同)

lon*_*ngi 33

阅读下面的更新

我有同样的问题,嵌入一个新的字体,最后得到它与扩展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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

UPDATE

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

更新2

从API Level 26开始,可在"支持库"中使用,您可以使用

android:fontFamily="@font/embeddedfont"
Run Code Online (Sandbox Code Playgroud)

更多信息:XML格式的字体

  • 这不是解决方案.我正在使用许多不同的视图,而不仅仅是TextView.我想设置一次字体而忘记它.此外,您的代码为每个TextView创建新对象.至少将该字段声明为静态以从资产加载字体一次. (24认同)
  • ...好吧,有一个查找和替换功能,在这种情况下效果很好 (2认同)

guy*_*guy 32

要更改您的应用字体,请执行以下步骤:

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

在此处输入图片说明

现在,您所有的应用程序文本都将位于您添加的文本中。

  • 使用自定义字体时,如何添加粗体和常规字体? (5认同)
  • 仅适用于 API 级别 26 及以上,那么 API 21 及以下呢? (4认同)

nir*_*rma 14

在 res/value/styles.xml 中添加这行代码

<item name="android:fontFamily">@font/circular_medium</item>
Run Code Online (Sandbox Code Playgroud)

整个风格看起来像这样

<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>
Run Code Online (Sandbox Code Playgroud)

将“circular_medium”更改为您自己的字体名称..


小智 8

在 Android Studio 中这非常非常容易。

  1. 在此方法中,您需要验证您的minsdkveriosn. 一定需要minsdkversion >=16

前任:

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

看图片:

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

前任:

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

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

前任:


All*_*han 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");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

ViewGroup group = (ViewGroup) getWindow().getDecorView().findViewById(android.R.id.content);
Font.setAllTextView(group);
Run Code Online (Sandbox Code Playgroud)

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


小智 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后只要您想覆盖字体,就可以调用方法并为其提供字体映射,如下所示:

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);
Run Code Online (Sandbox Code Playgroud)

完整的示例检查

这仅适用于Android SDK 21及更高版本(对于早期版本),请查看完整示例


Moh*_*yed 5

只需使用此lib在您的成绩文件中编译即可

complie'me.anwarshahriar:calligrapher:1.0'
Run Code Online (Sandbox Code Playgroud)

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

Calligrapher calligrapher = new Calligrapher(this);
calligrapher.setFont(this, "yourCustomFontHere.ttf", true);
Run Code Online (Sandbox Code Playgroud)

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