本文关键字:Android, 字体消失, 替换字体, 雅黑, 微米黑, 丽黑, 兰亭黑

一、Android字体简述

Android是一个典型的Linux内核的操作系统。在Android系统中,主要有DroidSans和DroidSerif两大字体阵营,从名字就可以看出来,前者是无衬线字体,后者是衬线字体。具体来说,一共是这几个字体文件:(位于 /system/fonts 目录下,需要root权限查看)

  • DroidSans-Bold.ttf   粗体的无衬线字体(拉丁字母等)
  • DroidSans.ttf   常规的无衬线字体(拉丁字母等)
  • DroidSansFallback.ttf   常规的无衬线字体(中文字符等)
  • DroidSansMono.ttf    等宽的无衬线字体(拉丁字母等)
  • DroidSerif-Bold.ttf    粗体的衬线字体(拉丁字母等)
  • DroidSerif-BoldItalic.ttf    粗体+斜体的衬线字体(拉丁字母等)
  • DroidSerif-Italic.ttf    斜体的衬线字体(拉丁字母等)
  • DroidSerif-Regular.ttf    常规的衬线字体(拉丁字母等)

除了这些字体文件,有些修改版本的 ROM,比如 CyanogenMod 5.0.8 ,还会有 Clockopia.ttf 之类的文件,从名字就可以看出这是显示数字时钟时用的字体。

上面提到的这些字体中,除了 DroidSansFallback.tff ,其它的一律不包含中文字体。而 DroidSansFallback 中的中文字体,是一种类似于文泉驿微米黑的字体,只是它的字库非常小,字符数量很少,估计只有 GB2312 的字符集,稍少见一些的字都是不包含的,比如我同学名字里有“祎”这个字,在联系人里就显示为一个方框。

二、替换字体

这样的小字库是不能令人满意的,而且,这种字体看久也觉得厌了,特别是在 iReader (Android电子书阅读软件)中看久了,就会觉得笔划越来越粗,长时间看了就疲劳了。那么替换字体也就显得很自然了。Android用的是标准的TrueType字体,因此只要把电脑里满意的字体改名后直接复制到 /system/fonts 目录下,用root权限覆盖掉原来的字体文件就好了。

我在 这篇文章 中提到过,我尝试了替换字体,我一开始是用的真正的Unicode的微米黑字体(这个字体的大小是4MB,系统原来的是3MB)替换的。但是有一些奇怪的问题。具体表述如下:

  1. 只替换DroidSansFallback.ttf,则一些尝试调用DroidSans和DroidSans-Bold的地方的字体都会显示为方框,整个手机只有英文字体和一小部分的中文字体可以显示,其它大部分都是方框。
  2. 如果把 DroidSansFallback, DroidSans, DroidSans-Bold 三个字体文件都替换,则不会有方框,但是系统里再也区分不出粗体与普通字体了。而且还要考虑到字体文件大小的问题,有些版本的ROM刷了之后 /system 下的剩余空间是很小的,放三个大字体根本不现实。(后面要提到的丽黑是8MB,兰亭黑是7M,雅黑则是14MB到20MB不等)
  3. 最诡异的来了,替换字体后,刚开机是没有问题的,问题就在过了一段时间后,所有的字体都会消失!所谓消失,就是所有该有字的地方都变成了空白,空白一片。这种情况出现的没有任何先兆,一般是开机用了一段时间就会有这种情况出现。如图:
android-font-missing-1
android-font-missing-2
android-font-missing-3
android-font-missing-5
android-font-missing-4

这种事情真是非常的令人讨厌,我还因为这件事情误格式化过一次microSD卡。(因为看不见按钮上的字)

三、问题何在?

出现了这种问题,自然要想办法去解决。我仔细观察回想了一下,一般都是开机之后运行了一些比较耗RAM的程序才会出现这种问题。比如开机之后运行Opera Mini 5,打开12个标签以上,右上角的时间字体就会消失,Action Bar里的文字也会同时消失,这种问题就重现了。考虑到RAM用了多了之后字体就消失了,我推断事情是这样的:开机载入了字体,放在RAM里,但是这种新替换的字体比系统自带的字体文件体积大很多,所以需要更多的RAM,而在运行了一些大程序之后,RAM不够了,字体文件就被踢出了RAM。

真的是这样吗?我当时认为的确是这样的,所以我干脆决定不用新字体了,就用老字体吧,就把之前备份的老字体文件全部用Root Explorer覆盖回去了,重启。现在应该没问题了吧?我故意运行了几个大程序……结果问题又重现了。

这就奇怪了,最早用老字体是从来没有这个问题的,换了新字体之后问题出现,但是用备份文件恢复到老字体,怎么还是有问题呢?

在后来相当长的一段时间内,我一直想不通这件事情,甚至还愤怒地把DroidSansFallback.ttf给删除了……当然,开机不能了。

重新用update.zip恢复了一下,冷静下来思考,替换前和替换后有什么是改变了的呢?在Root Explorer再仔细看看……似乎是权限改变了!

Linux文件系统里的文件都是有权限的,且与Windows文件系统里的权限概念有一些区别。三个权限者,Owner, Group, World(Other),每人都有三项权限,分别是 Read(r), Write(w) 和 Execute(x) 。其中代表Read的数字为4,代表Write的数字为2,代表Execute的数字为1,这样就可以用1-7的自然数还表示不同的权限。比如R+W就是6,R+W+X就是7,R+X就是5,等等。三个权限者分别排列,就有了755,777等这样的代表权限组合的数字。

Linux的这套权限系统可以用chmod命令来修改,但是在Root Explorer里修改起来更加方便一些。

长按文件,然后就有一个Permissions的选项,点击之,打开的窗口里就可以改权限了,当然前提是 mount as r/w。

如下面左图,这是 /system/fonts 目录下原生的一个文件,而右图则是从 /sdcard 里复制进去的文件,对照两张图就可以看出权限发生了改变。(由644变成了075)

从图中可以看到,原来的文件对于User来说是有R/W权限的,而从 /sdcard 里复制进来的文件对于User是没有R/W权限的。这就是问题所在了!这也很容易解释,为什么最早不会有字体消失问题,然后替换了字体(从外面复制进来权限不正确的字体)后字体就消失了,但是用备份文件恢复(重新又从外面复制进来字体)后,字体消失问题还是存在!这是因为在复制过程中,由于文件系统的不统一(ext2和FAT32),导致权限错乱。

四、如何解决?

知道了问题的所在,解决起来就非常容易了——在替换完字体之后不要急着重启,一定要对照其它的文件,把新复制进来的那些文件的权限改成正确的644!

五、特别关照

  1. 字体是放在 /system/fonts 目录下的,这个目录属于 /system 分区,因此你先要确保 /system 分区的剩余空间是够的。
  2. /system 分区剩余空间不够怎么办?那就删除自带的程序。由于我做了Apps2SD,所以我的 /data 分区( /sd-ext 分区)的剩余空间是足够的,那么就可以把系统自带的程序移到 /sd-ext 下面?怎么移动呢?参照这篇文章:《如何把Android自带程序移动到其它分区以腾出 /system 分区的空间》
  3. 对于屏幕显示来说,还是无衬线字体比较适合,衬线字体么,还是让它们在印刷上发挥作用吧。我看到有一些人把那些“华康少女简体”之类的手写衬线字体当作Android的默认字体……这实在是不恰当的行为。虽然一开始会觉得很惊艳,但是时间长了之后眼睛会疲劳,对视力并不好。所以还是要选无衬线字体的好。

六、字体推荐

看上面这四幅图,前三张是我在Android上实际截图得到的,分别是用兰亭黑、丽黑、雅黑作为默认字体。最后一张是Windows 7里微软雅黑字体的显示效果。需要注意的是,虽然我的系统里以注册表方式加载了GDI++,但是我在截那张图的时候是用GDI++Inject把Notepad.exe的GDI++模块卸载掉的,所以最后一张图是没有任何额外渲染的本来效果。

都说实践出真知,通过这次替换我才真正尝试出了最适合Android的字体。同一个字体,在不同的系统里、以不同的方式渲染,显示出来的效果也是有很大不同的。比如兰亭黑在Ubuntu下面好看的,在Android下就很一般,丽黑是Mac OS X的默认字体,有多漂亮大家肯定都见到过,但是在Android上的显示效果呢?笔划粗大、粘连,看得时间长了很容易眼疲劳。而微软雅黑这款MS花了重金打造的字体呢?它的Windows下的显示效果……说真的,很差。至少不用第三方字体渲染的情况下很糟糕,可是,当我抱着试试看的态度把它复制到Android之后,我才发现它的显示效果如此之好:字面大、笔划清晰、结构平稳、构架匀称……简直是Android下的极品字体啊。

这样的字体哪里有?心动的同学就不要到网上去搜索了,网上很多是修改版本的,虽然字体小,但是具体改了什么东西我就不清楚了,我不能保证它能像图中显示的那么好看,所以……大家可以像我一样,从Windows 7的字体目录里复制。(默认是 C:\Windows\Fonts )

(全文完)

转载时请标注本文地址,谢谢。


欢迎留下评论。评论前,请先阅读《隐私声明》。