Android 字体字重(Font Weight)设置全攻略:从 XML 黑科技到 Kotlin 动态实现

46 阅读3分钟

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

四、 常见问题与坑点

  1. 版本兼容性android:textFontWeight 仅在 API 28+ 生效。在旧设备上,它会被完全忽略。
  2. 厂商定制:部分国产手机系统精简了内置字体库。如果你设置 500 和 600 看起来完全一样,那是因为系统字库里只有 Regular 和 Bold 两个物理文件。
  3. 空 XML 的风险:虽然空 font-family 在新系统上有效,但为了代码健壮性,建议在 XML 中显式指向 @android:font/sans_serif

五、 总结

  • 追求极简:使用空 font-family XML + android:textFontWeight
  • 追求兼容:使用 android:fontFamily="sans-serif-medium"
  • 追求精准动态:使用 Kotlin 的 Typeface.create(typeface, weight, false)

通过灵活运用系统默认资源,你可以在不增加一比特包体积的前提下,打造出极具设计感的视觉体验。


我可以为您做的下一步:

如果您觉得博客内容已经足够,我可以帮您将这些代码片段整理成一个可以直接复制使用的 Kotlin 工具类文件;或者如果您想增加一些关于“可变字体(Variable Fonts)”的高阶内容,我也可以补充。需要哪个?