如何阻止系统字体覆盖Android应用自定义字体?
强制Android应用使用指定字体,不受系统字体替换影响
这个问题我之前也碰到过,核心原因是你配置的sans-serif是系统默认字体的别名——当用户在手机设置里更换字体时,系统会把这个别名指向用户选择的字体,所以你的全局样式和单独设置都会被系统覆盖。下面给你几个可靠的解决方案:
方案一:嵌入字体文件(最推荐)
直接把你想要的Roboto字体文件打包到应用里,彻底摆脱系统字体的影响:
导入字体文件
- 下载Roboto字体的对应字重文件(比如
Roboto-Regular.ttf),放到app/src/main/assets/fonts/目录下(如果没有fonts文件夹就手动创建)。 - 或者在Android Studio里右键
res目录 →New→Font resource file,创建一个字体资源文件(比如roboto_regular.xml),这样更兼容Android 8.0+的字体特性:<?xml version="1.0" encoding="utf-8"?> <font-family xmlns:android="http://schemas.android.com/apk/res/android"> <font android:fontStyle="normal" android:fontWeight="400" android:font="@font/roboto_regular" /> </font-family>
- 下载Roboto字体的对应字重文件(比如
修改全局样式
把原来的RobotoTextViewStyle改成直接引用嵌入的字体:<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> <item name="android:textViewStyle">@style/RobotoTextViewStyle</item> </style> <style name="RobotoTextViewStyle" parent="android:Widget.TextView"> <!-- 兼容Android 8.0+的写法 --> <item name="android:fontFamily">@font/roboto_regular</item> <!-- 兼容AppCompat库的写法 --> <item name="fontFamily">@font/roboto_regular</item> <!-- 旧版本兼容写法(Android 7.1及以下) --> <!-- <item name="android:typeface">file:///android_asset/fonts/Roboto-Regular.ttf</item> --> </style>
方案二:自定义TextView(更灵活)
如果需要对字体做更多自定义操作,比如动态切换字重,可以创建一个自定义TextView类,在代码里强制加载嵌入的字体:
public class RobotoTextView extends AppCompatTextView { public RobotoTextView(Context context) { super(context); initFont(); } public RobotoTextView(Context context, AttributeSet attrs) { super(context, attrs); initFont(); } public RobotoTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initFont(); } private void initFont() { // 加载assets里的Roboto字体 Typeface robotoRegular = Typeface.createFromAsset(getContext().getAssets(), "fonts/Roboto-Regular.ttf"); setTypeface(robotoRegular); } }
之后在布局文件里直接使用这个自定义TextView:
<com.yourpackage.RobotoTextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" />
为什么原来的方法无效?
再次强调:sans-serif是系统默认字体的别名,系统字体更换后,这个别名会被系统重新指向用户选择的字体,所以你的样式设置会被系统优先级更高的配置覆盖。只有直接引用应用内部的字体文件,才能彻底避免这种情况。
内容的提问来源于stack exchange,提问作者fcberg
相关产品推荐
相关产品推荐

