Android替换字体时需要注意的一些问题

本文关键字: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 )

(全文完)

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

Leave a comment

19 Comments.

  1. …沙发,小允哥哥挺牛的嘛~

    Google Chrome 3.0.195.0 Google Chrome 3.0.195.0 Windows XP Windows XP
    Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/531.0 (KHTML, like Gecko) Chrome/3.0.195.0 Safari/531.0 SE 2.X
    • @Aveline .L, 呵呵……小兔子怎么又换名字了呀?

      Google Chrome 5.0.324.0 Google Chrome 5.0.324.0 Windows 7 Windows 7
      Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.1 (KHTML, like Gecko) Chrome/5.0.324.0 Safari/533.1
      • @wzyboy, 呃,换了好久了哇

        Google Chrome 3.0.195.0 Google Chrome 3.0.195.0 Windows XP Windows XP
        Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/531.0 (KHTML, like Gecko) Chrome/3.0.195.0 Safari/531.0 SE 2.X
  2. 来访拉 记得回访哦!!祝福你的空间人气越来越旺哦 ! 嘻嘻 我叫 多多 可以做个朋友吗?

    Internet Explorer 8.0 Internet Explorer 8.0 Windows XP Windows XP
    Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; QQPinyin 689; QQPinyin 722; GTB6.5; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
  3. 权限和文件系统没啥关系吧…(在Ubuntu下)你用root考user的文件,考过去的文件所有者是root,用user考root的文件,考过去的文件所有者是user.那么..你在复制字体的时候应该是用的root权限,然后忘了把权限改成user,所以就那啥了.
    (另外我折腾linux不折腾Android,以上仅代表个人猜想)

    Google Chrome 5.0.375.99 Google Chrome 5.0.375.99 GNU/Linux GNU/Linux
    Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.99 Safari/533.4
    • 被你这么一说我特意试了下,把一个 /system/fonts 里的文件复制到 /data 下面,然后再改个名字复制到原处,结果…文件权限没有改变。然而我把那个文件复制到FAT32的 /sdcard 下面,改名后复制回来,权限就变化了…

      Unknown Unknown Android Android
      wp-android/1.2
      • @wzyboy,
        啊~?…真有这种事?你用的什么权限考的文件?

        Google Chrome 5.0.375.99 Google Chrome 5.0.375.99 GNU/Linux GNU/Linux
        Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.99 Safari/533.4
      • @wzyboy,
        为什么我的IP是澳大利亚的~?

        Google Chrome 5.0.375.99 Google Chrome 5.0.375.99 GNU/Linux GNU/Linux
        Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.99 Safari/533.4
      • @wzyboy,
        好吧,在Ubuntu下,用user在不同分区类型的分区间考文件不会发生权限错乱,但用root会.

        Google Chrome 5.0.375.99 Google Chrome 5.0.375.99 GNU/Linux GNU/Linux
        Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.99 Safari/533.4
        • @雨碎江南, 汗。 /system 分区只有root才能读写,所以我是用root权限拷贝的……

          Opera Mini 4.2.14427 Opera Mini 4.2.14427 J2ME/MIDP Device J2ME/MIDP Device
          Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.14427/19.836; U; en) Presto/2.5.25
      • @wzyboy,
        这算Bug吗?…Linux kernel的Bug…

        Google Chrome 5.0.375.99 Google Chrome 5.0.375.99 GNU/Linux GNU/Linux
        Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.99 Safari/533.4
  4. 看了你这篇文章我也很想尝试GDI++,但是据说那个配置比较乱遭,知道和硬件有关,但是可否把你的配置文件发我一份我参考参考

    Firefox 3.6.4 Firefox 3.6.4 Windows XP Windows XP
    Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.4) Gecko/20100527 Firefox/3.6.4
  5. GDI++是什么玩意?

    Google Chrome 5.0.375.99 Google Chrome 5.0.375.99 GNU/Linux GNU/Linux
    Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.99 Safari/533.4
    • @Achmany, 是一个可以增强字体渲染效果的玩意,Windows下用的

      Google Chrome 5.0.324.0 Google Chrome 5.0.324.0 Windows 7 Windows 7
      Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.1 (KHTML, like Gecko) Chrome/5.0.324.0 Safari/533.1
  6. 改渲染模式?

    Avant Browser Avant Browser Windows XP Windows XP
    Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; MyIE2; GTB6.3; Avant Browser; InfoPath.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; Maxthon 2.0)
  7. hihi,我想请教一下,如果我只想替换系统的英文应该拿哪个开刀呢?因为我是用英文的。

    Maxthon 2.0 Maxthon 2.0 Windows 7 Windows 7
    Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.2; Maxthon 2.0)

Leave a Reply


[ Ctrl + Enter ]

Note: Commenter is allowed to use '@User+blank' to automatically notify your reply to other commenter. e.g, if ABC is one of commenter of this post, then write '@ABC '(exclude ') will automatically send your comment to ABC. Using '@all ' to notify all previous commenters. Be sure that the value of User should exactly match with commenter's name (case sensitive).