0%

Android 字体那些事

相关概念

自带字体

Android 中默认字体是 Roboto,4.0 引入,5.0 进行了大的改良。

中文 5.0 之前是 Droid,之后是 Noto Sans「思源黑体」。

字体属性

android:typeface属性是自 API-1 以来就被添加进系统的,不能引用外部字体,只允许被设置为以下四种typeface:

  • normal
  • sans
  • serif
  • monospace

android:fontFamily 对 typeface 的一次加强,可以支持更多的字体样式,例如:

  • casual
  • cursive
  • condensed
  • serif-monospace

fontFamily 优先级比 typeface 高,同时被设置的话,后者会自动失效
fontFamily的某些字体是有系统版本限制的,比如 sans-serif-medium 是 5.0 之后才添加的,版本支持情况可以看这个回答

连字

连字(也称合字,英文为 Ligature,维基)是字体和排版里面的一个概念。有些字体里面当 字母f 和 字母i 连在一起的时候, f 的一横会跟 i 的一点撞上,导致不好排版。 所以为了方便、美观,有些字体直接会有 fi 连字的字模。

支持连字的 Fira Code 宣称自己是最适合程序员的编程字体。

自定义字体

自定义字体引入方式

Fonts in XML

Android 8.0 引入了 Fonts in XML,通过 support 包可以在 4.1 及以上系统使用。步骤:

  1. res 目录下创建 font 目录,并放入字体文件
  2. 创建一个 font family 的 resource 文件
  3. 通过 android:fontFamily=”@font/lobster” 进行设置

通过代码加载

1
2
val tf = Typeface.createFromAsset(context.getAssets(), "fonts/helveticaneue.ttf");
textView.typeface = tf

全局替换字体

使用 Theme

Application 节点设置自定义的 theme,在 theme 中设置 fontFamily

反射

1
2
3
4
final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets);
final Field defaultFontTypefaceField = Typeface.class.getDeclaredField("SERIF");
defaultFontTypefaceField.setAccessible(true);
defaultFontTypefaceField.set(null, customFontTypeface);

按页面替换(使用 Calligraphy)

通过 ViewPump 项目自定义 LayoutInflater

引入 Calligraphy,注册拦截器 CalligraphyInterceptor

在 onViewCreated 方法中进行替换

使用自定义 TextView

这个比较简单,自定义 TextView 中设置字体,然后所有地方使用自定义的控件即可,代价是代码侵入性比较高。

Downloadable Fonts

多个应用通过一个提供程序可以共享同一种字体,从而提升了整个系统的健康。如此可节省用户的数据流量、手机内存以及存储空间。此模式下字体文件会在需要时通过网络获取,可以减小 APK 的大小。

目前只能通过 Google Play 服务使用。