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

当前回答

我们是这样做的:

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

其他回答

不谈性能,对于自定义字体,你可以有一个递归方法循环通过所有的视图和设置字体,如果它是一个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);

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

这在Android Studio中非常非常简单。

在这个方法中,你需要验证你的minsdkverison。minsdkversion >=16

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

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

在你的style.xml文件中,在“Base application theme”的style下添加这一行。 <项目名称= " android: fontFamily " > @font / ubuntubold > < /项目

更多的细节: https://coderog.com/community/threads/how-to-set-default-font-family-for-entire-android-app.72/

Android并没有在整个应用程序中应用字体的方式上提供很多支持(参见本期)。你有4个选项来设置整个应用程序的字体:

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

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

答案是肯定的。

TextView和Button类的Global Roboto light:

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

只需从list 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: prefix,但textViewStyle必须包含它。

另一种方法是在整个应用程序中使用基于这个答案的反射

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及以上的早期版本,检查完整的示例