将自定义字体设置为所有TextView

6

有没有一种简单的方法,可以使我的应用程序中所有的textviews(和其他文本元素)都使用我自己的自定义字体(而不是内置选择),而不必通过textview.setTypeface()手动设置它们?

我猜扩展Textview会起作用,但是使用可视化编辑器构建界面有点麻烦。我想到了类似于样式的东西,但找不到如何在那里设置自定义字体。


请检查以下链接:https://dev59.com/Q2w05IYBdhLWcg3w72bN 和 https://dev59.com/xWox5IYBdhLWcg3wQSEO。 - Lia Pronina
嗨@MichelReap,如果我的回答解决了你的问题,请标记为已接受。 - Paras Valera
5个回答

14
如果您需要为Android应用程序中的所有TextView设置一个字体,可以使用此解决方案。它将覆盖所有TextView的字体类型,包括操作栏和其他标准组件,但不会覆盖EditText的密码字体。 MyApp.java
    public class MyApp extends Application {

    @Override
    public void onCreate()
    {
                TypefaceUtil.overrideFont(getApplicationContext(), "SERIF", "fonts/Roboto-Regular.ttf"); 
     }
    }

TypefaceUtil.java

public class TypefaceUtil {

    /**
     * Using reflection to override default typeface
     * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE OVERRIDDEN
     * @param context to work with assets
     * @param defaultFontNameToOverride for example "monospace"
     * @param customFontFileNameInAssets file name of the font from assets
     */
    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) {
            Log.e("TypefaceUtil","Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride);
        }
    }
}

主题.xml

     <?xml version="1.0" encoding="utf-8"?>
   <resources>
     <style name="MyAppTheme" parent="@android:style/Theme.Holo.Light">
    <!-- you should set typeface which you want to override with TypefaceUtil -->
    <item name="android:typeface">serif</item>
   </style>
   </resources>

适用于Android 5.0或更高版本的更新

我经过调查和在运行API 5.0或更高版本的设备上进行测试,发现该解决方案效果很好,因为我正在使用单个style.xml文件,而不是在values-21文件夹中创建其他style.xml文件。

尽管如此,有些用户告诉我这个解决方案在Android 5.0设备上无法正常工作(我猜他们可能在使用values-21 style.xml)。

原因是,在API 21以下的大多数文本样式中包括fontFamily设置,比如:

<item name="fontFamily">@string/font_family_body_1_material</item>

应用默认的Roboto常规字体:

<string name="font_family_body_1_material">sans-serif</string>

所以最好的解决方案是

如果有人遇到5.0以上版本无法工作的问题,请不要在您的values-v21样式中覆盖typeface。

只需在values/style.xml中覆盖字体,您就可以使用了 :)


1
在许多设备上表现良好。但是我尝试在一些设备上,例如三星S5(5.0.1),它无法工作。 - Eurig Jones
@Lena,我们正在使用@style/Theme.AppCompat.Light.NoActionBar,但它不起作用。 - Prags
你收到了什么结果? - Lena Bru
2
这是源代码吗?github gist by artem-zinnatullin - 如果是的话,你应该给予信用;如果不是,则应该在此gist上请求信用。 - Talha
我已经在我的应用程序中实施了上述方法。它适用于大多数语言。但是在4.4.4三星设备上,缅甸字体无法正确加载。请建议。应用程序图像截图在此处-> https://ibb.co/gvzOXv - Vinay Kashyap T S
@user3752389 很高兴听到它对你和其他开发者有所帮助。顺便说一下,你可以点赞回答;关于你在 4.4.4 设备上的问题,我们需要更多细节来纠正它。 - Paras Valera

1
你可以创建一个方法在一个公共类中设置textview的字体,并且通过将textview作为它的属性来调用该方法。

0
在Constants类中创建一个方法,以便可以从所有片段和活动中访问它:
 public static void overrideFonts(final Context context, final View v) {
    try {
        if (v instanceof ViewGroup) {
            ViewGroup vg = (ViewGroup) v;
            for (int i = 0; i < vg.getChildCount(); i++) {
                View child = vg.getChildAt(i);
                overrideFonts(context, child);
            }
        } else if (v instanceof TextView) {
            ((TextView) v).setTypeface(Typeface.createFromAsset(context.getAssets(), "font/Lato-Regular.ttf"));
        } else if (v instanceof EditText) {
            ((EditText) v).setTypeface(Typeface.createFromAsset(context.getAssets(), "font/Lato-Regular.ttf"));
        } else if (v instanceof Button) {
            ((Button) v).setTypeface(Typeface.createFromAsset(context.getAssets(), "font/Lato-Regular.ttf"));
        }
    } catch (Exception e) {
    }
}

在活动中调用方法:

 Constants.overrideFonts(MainActivity.this, getWindow().getDecorView().getRootView());

在Fragment中调用方法的方式如下:

  Constants.overrideFonts(getActivity(), view);

0

可以的。只需创建一个样式并将其设置为特定字体,然后将整个应用程序设置为该样式即可。


0
你可以通过创建 TextView 的子类,在其中调用 setTypeFace 方法来实现。例如在构造函数中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接