优雅并极客地添加/更改Android系统的字体

Android换字体有很多办法,其一是用iFont之类的工具,优雅但不极客。其二是用root权限直接到/system/fonts里替换DroidSansFallback来更改中文字体,极客但是非常不优雅!

看看/system/etc/fallback_fonts.xml吧,注释都告诉我们如何优雅并极客地添加字体了。下面以添加苹果iOS自带的中文字体STHeiti为例,详细讲述一下整个过程。

Android系统对字体的载入和Linux桌面很像,有一个Priority Order(优先级顺序)的,当然先是西方字符,然后是一些符号字体(包括emoji字体),再就是中日韩字符(DroidSansFallback.ttf包含了全部CJK的字符,但是日文字符有专门的MTLmr3m.ttf来显示,不过Android默认为仅在语言区域为日本(”ja”)的时侯才把MTLmr3m优先于DroidSansFallback)。这个字体载入顺序是以XML格式的配置文件保存在/system/etc下的,一共两个配置文件,分别是system_fonts.xml和fallback_fonts.xml,其中system_fonts.xml基本只有拉丁子母集(指定了常见的Serif、Sans、Times New Roman、Monospace对应的字体),而fallback_fonts.xml则囊括了其它全部语言、符号的字体。

讲完枯燥的基本原理,下面开始讲具体操作过程。

  1. 首先创建一个fallback_fonts.xml文件,适用于Android 4.4.2(CM11)的参考内容如下(Windows平台建议用Notepad++来编辑),这里面,标签的属性order=”29″是数/system/etc/fallback_fonts.xml里DroidSansFallback所在的顺序(从0开始)数出来的,29就是DroidSansFallback,这里指定order=”29″就把新增的这段字体族插入到DroidSansFallback前面了(插入到第29个,DroidSansFallback因此顺移到后面)。你也可以指定oder=”0″直接插入到Fallback Priority的顶端(注:即便是0也不能比Roboto即system_fonts.xml优先)
<?xml version="1.0" encoding="utf-8"?>
<!--
Vendor-provided fallback fonts

This file can be edited to add references to fonts that are not installed or referenced in the
default system. The file should then be placed in /vendor/etc/fallback_fonts.xml.
See /system/etc/system_fonts.xml and /system/etc/fallback_fonts.xml for more information
and to understand the order in which the default system fonts are loaded and structured for
lookup.
-->
<familyset>
    <family order="29"><!-- start with 0. No.29 is DroidSansFallback in Android 4.4 KitKat -->
        <fileset><!--Replace it with iOS STHeitiSC-->
            <file>STHeitiSC-Light.ttf</file>
            <file>STHeitiSC-Medium.ttf</file>
        </fileset>
    </family>
</familyset>
  1. 准备好STHeitiSC-Light.ttf和STHeitiSC-Medium.ttf两个字体文件,这两个文件是通过分解iOS自带的CJK(中日韩)字体STHeiti-Light.ttc和STHeiti-Medium.ttc转换成ttf字体而来,SC的意思是简体中文(Simplified Chinese)。戳这里去百度网盘下载。
  2. 通过adb push指令或者用存储卡、USB连接等方式,把第一步编辑的fallback_fonts.xml文件、第二步的ttf字体文件传输到手机内置存储器(或存储卡)里,我这里复制到了/sdcard/下。
  3. 打开CM自带的File Manager(文件管理器)或者Root Explorer(R.E.管理器),将ttf字体文件复制到/system/fonts/下(需要root权限),并将ttf字体权限改为644(Owner、Group、Others都要有R即「读」的权限,仅Owner拥有W即「写」的权限),再将fallback_fonts.xml文件复制到/system/vendor/etc/下(需要root权限),同样更改为644的权限。
  4. 重启手机。
左为STHeitiSC,右为DroidSansFallback
左为STHeitiSC,右为DroidSansFallback

比较Android 4.4 KitKat原生DroidSansFallback和STHeitiSC的原始截图文件可以从第二步给出的百度网盘下载到,两张图切换看更能看得出差异。

本文给出的办法优点在于新增的字体不需要非常全面去替换DroidSansFallback,甚至可以只有简体字,因为插入到DroidSansFallback的前方,所以当Android系统遇到新增的字体(本例中的STHeitiSC)无法显示的字符时,就会继续fallback到下一个字体(DroidSansFallback)。

缺点就是依然需要root,并且不适合ROM空间非常小的机器(新加入的中文字体体积都不小,一个就10~30MB)。

注意:STHeiti的版权归Apple所有,本文共享的TTF文件仅供学习一种Android字体添加和管理的方法,毕竟现在Android的默认中文字体质量和iOS的差别不大。如遇侵权,责任自负。

加注:
偷懒不想自己一步一步做的,第二步给的百度网盘链接中的stheitisc_patch.zip是懒人一键刷入STHeitiSC的包(因为oder=”29″,所以仅适用于Android 4.4,低版本的刷入后需要手动修改order的值),通过CWM或TWRP等第三方Recovery刷入即可。

 

Update. 08-May-2014

至少从CM11 Snapshot M6起,又新增了一个字体文件,DroidSansFallBack的order要加一。因此本文中提到的order需要改为30,否则emoji会无法显示。

使用此法一定要保证order的值是恰当的,建议按照本文方法手动寻找恰当的order,同时停止提供懒人包。

Comments

21 responses to “优雅并极客地添加/更改Android系统的字体”

  1. Yu avatar
    Yu

    网盘链接失效了?

    1. librehat avatar

      恩,决定取消分享了(上次更新文章的时侯写的「停止提供懒人包」)。

      1. Yu avatar
        Yu

        哦,我是找不到这两个字体。。。
        另外今天拿其他字体替换的时候发现,系统会先调用之前一个字体叫NanumGothic,需要先把这个调用屏蔽才会用调用DroidSansFallback,系统4.4.2 Slim

        1. librehat avatar

          毕竟字体也有知识产权,而且文章中把方法都讲到了,所以就不分享了。:-)
          没用过Slim,这样的话你可以用本文的办法把DroidSansFallback「挪到」NanumGothic前面。

          1. Yu avatar
            Yu

            我查了下发现NanumGothic好像是韩文字体,所以就直接把NanumGothic的引用链接删掉了,毕竟把DroidSansFallback放到前面会影响Emoji字体的引用,目前看来这样做还算稳定

          2. librehat avatar

            恩,删除当然是可以的。字体改动最多弄得看不到字……稳定性上不会有影响的。

  2. AA avatar
    AA

    我也试过把 【_JPN】删了,没有效果

    1. librehat avatar

      机器是定制版,加了很多字体了,Samsung打头的这些都是一般ROM里没有的。
      你可以把DroidSansFallback.ttf挪到Samsung*.ttf前面吧。我这篇文章就是提供一个方法,具体情况肯定得自己具体分析。

      1. AA avatar
        AA

        好吧,先谢谢你了,我再一一试试

  3. AA avatar
    AA

    不过Android默认为仅在语言区域为日本的时侯才把MTLmr3m优先于DroidSansFallback

    怎么取消MTLmr3m优先? 语言区为日本不变的情况下

    1. librehat avatar

      /system/etc/fallback_fonts.xml里,MTLmr3m有lang=”jp”的标签簇,删除该标签簇即可。。

      1. AA avatar
        AA

        在我这边的fallback_fonts.xml文件里压根就没有
        【MTLmr3m有lang=”jp”的标签簇】之类的信息啊

        UDGothic-Regular.ttf
        UDGothic-Bold.ttf
        UDGothic-Italic.ttf
        UDGothic-BoldItalic.ttf

        truetypeEmoji.ttf

        SamsungEmoji.ttf

        GS45_Arab_AndroidOS.ttf

        DroidSansEthiopic-Regular.ttf

        DroidSansHebrew-Regular.ttf
        DroidSansHebrew-Bold.ttf

        SamsungThai.ttf

        DroidSansArmenian.ttf

        DroidSansGeorgian.ttf

        SamsungBengali.ttf

        SamsungDevanagari.ttf

        SamsungGujarathi.ttf

        SamsungKannada.ttf

        SamsungMalayalam.ttf

        SamsungOriya.ttf

        SamsungPunjabi.ttf

        SamsungSinhala.ttf

        SamsungTamil.ttf

        SamsungTelugu.ttf

        DroidSans_Subset.ttf

        SamsungKorean.ttf
        SamsungKorean-Bold.ttf

        DroidSansFallback_JPN.ttf

        AndroidEmoji.ttf

        DroidSansFallback.ttf

        1. AA avatar
          AA

          难道是我这手机是日版的原因么?SC-03E

        2. librehat avatar

          你这里就没有MTLmr3m.ttf好么。
          DroidSansFallback_JPN.ttf这个应该对应的是日文字体,它的顺序在DroidSansFallback.ttf前面。你要么删掉DroidSansFallback_JPN.ttf串,要么把DroidSansFallback.ttf族提前到前面去。

          1. AA avatar
            AA

            DroidSansFallback_JPN.ttf我打开看了,里面的字体和现在显示的不一样,而MTLmr3m.ttf到是和现在显示的一样啊

  4. aaron avatar
    aaron

    博主我按照你的方法做(没有下懒人包),现在情况是字体是正确了 但是主屏还有设置啊什么的里面字体非常小,大小就像是word里面的下标一样。但是网页内容里的字大小是正常的。这应该怎么解决?谢啦

    1. librehat avatar

      是不是你没有把OTF格式字体转换成TTF格式?

      1. aaron avatar
        aaron

        我用的就是你放在baidu网盘上的, 都是ttf的文件。后来我用了网上下的微软yahei的ttf成功了。估计是ttf的问题。

        1. librehat avatar

          恩……你不是说你没用懒人包么。。无从查验了,应该是TTF格式的问题。

  5. yhlfh avatar

    博主这招很牛叉啊!~这应该是Android替换字体最佳方案。

    1. librehat avatar

      也是一路Google摸索实验来的,这个办法确实是目前感觉最好的。