在 Android 开发中,精准控制字体的粗细(Weight)是提升 UI 精致度的关键。很多开发者习惯于直接引入外部 .ttf 字体文件,但其实利用系统默认字体和一些“隐藏技巧”,我们也能实现细腻的字重控制。
本篇博客将带你解锁如何在不增加包体积的情况下,优雅地设置 Font Weight。
一、 核心概念:什么是 FontWeight?
在 Android 9.0(API 28)之前,我们对字体粗细的选择非常有限,通常只有 normal 和 bold 两种样式。
而现代 Android 系统支持 1-1000 的字重数值:
- 400: Normal (常规)
- 500/600: Medium / Semi-Bold (中等粗细)
- 700: Bold (粗体)
二、 XML 实战:一个“空文件”引发的奇迹
你可能发现,在 res/font 目录下创建一个几乎为空的 font-family 文件,配合 android:textFontWeight 属性,竟然能奇迹般地改变系统字体的粗细。
1. 创建配置文件
在 res/font/system_font.xml 中:
XML
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
</font-family>
2. 在布局中使用
XML
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/system_font"
android:textFontWeight="600"
android:text="精准控制字重" />
原理揭秘: 这种做法通过 fontFamily 资源触发了系统的 Font Fallback(回退)机制。当 XML 为空时,系统指向默认字体族(Roboto),由于设置了 textFontWeight,系统会从默认族中寻找最接近 600 的字重文件进行渲染。
三、 Kotlin 进阶:动态设置字重
如果你需要在代码中根据业务逻辑(如搜索高亮、动态主题)改变字重,可以使用以下兼容性方案:
1. 针对 Android 9.0+ 的精准控制
Kotlin
fun TextView.setFontWeight(weight: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
// Typeface.create(Typeface, Weight, isItalic)
this.typeface = Typeface.create(this.typeface, weight, false)
}
}
2. 全版本兼容扩展函数
为了兼顾旧版本,我们可以编写一个扩展函数,在低版本上使用系统预设的别名:
Kotlin
fun TextView.setSmartFontWeight(weight: Int) {
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P -> {
this.typeface = Typeface.create(this.typeface, weight, false)
}
weight >= 500 -> {
// 低版本回退到系统预设的中等粗细
this.typeface = Typeface.create("sans-serif-medium", Typeface.NORMAL)
}
else -> {
this.typeface = Typeface.DEFAULT
}
}
}
四、 常见问题与坑点
- 版本兼容性:
android:textFontWeight仅在 API 28+ 生效。在旧设备上,它会被完全忽略。 - 厂商定制:部分国产手机系统精简了内置字体库。如果你设置 500 和 600 看起来完全一样,那是因为系统字库里只有 Regular 和 Bold 两个物理文件。
- 空 XML 的风险:虽然空
font-family在新系统上有效,但为了代码健壮性,建议在 XML 中显式指向@android:font/sans_serif。
五、 总结
- 追求极简:使用空
font-familyXML +android:textFontWeight。 - 追求兼容:使用
android:fontFamily="sans-serif-medium"。 - 追求精准动态:使用 Kotlin 的
Typeface.create(typeface, weight, false)。
通过灵活运用系统默认资源,你可以在不增加一比特包体积的前提下,打造出极具设计感的视觉体验。
我可以为您做的下一步:
如果您觉得博客内容已经足够,我可以帮您将这些代码片段整理成一个可以直接复制使用的 Kotlin 工具类文件;或者如果您想增加一些关于“可变字体(Variable Fonts)”的高阶内容,我也可以补充。需要哪个?