標籤:

Magisk 模塊字體為什麼這麼好用,因為它有這些優點!

2018 年 5 月,SuperSU 的作者 Chainfire 正式宣布停止開發所有 root 相關的應用,這個消息曾一度讓許多人認為是 Android 玩機時代的落幕。

用塵封之淚大神的話來說,就是:

Chainfire 是真正的大神,能夠做到像 Chainfire 這樣的人並不多。

但誰也沒想到,此前一直不溫不火的 Magisk 卻在這個時候站了出來並成功扛過了 root 工具的重擔。現在,Magisk 不僅做到了 Android Q 一問世就立即解決了 root 問題,還為玩機的朋友提供了掛載各種優化模塊,甚至結合一些開發者的作品在 Androd 9 上實現了需要依賴 Xposed 框架才能實現的功能(在 Xposed 的作者 rovo89 自己都還沒搞定 Android 9 適配的前提下,這是一件非常 amazing 的事情)。

不過,今天主要講通過 Magisk 換字體的話題,Magisk 模塊字體為什麼這麼好用?

Android 是如何呈現字體的?

要回答上面這個問題,得先從 Android 手機的字體調用規則說起。

Android 5.0 之後,幾乎整個手機的字體效果都由 fonts.xml 這個配置文件來掌控,它位於 system/etc 路徑下,起到對 system/fonts 路徑下的字體文件進行全局調配的中樞級作用。

之所以用上「幾乎」這個詞,是因為 Android 手機環境複雜,各大廠商喜歡魔改系統,也難免動到和字體有關的地方。因此通過修改 fonts.xml 這個配置文件以及 system/fonts 這些字體文件也許只能實現 95% 左右的字體替換覆蓋效果,只有在原生安卓系統上才能 100% 全局生效。

為什麼要進行這樣的修改呢?在 fonts.xml 中,有一段很關鍵的代碼:

<family name="sans-serif">

<font weight="100" stylex="normal">Roboto-Thin.ttf</font>

<font weight="100" stylex="italic">Roboto-ThinItalic.ttf</font>

<font weight="300" stylex="normal">Roboto-Light.ttf</font>

<font weight="300" stylex="italic">Roboto-LightItalic.ttf</font>

<font weight="400" stylex="normal">Roboto-Regular.ttf</font>

<font weight="400" stylex="italic">Roboto-Italic.ttf</font>

<font weight="500" stylex="normal">Roboto-Medium.ttf</font>

<font weight="500" stylex="italic">Roboto-MediumItalic.ttf</font>

<font weight="900" stylex="normal">Roboto-Black.ttf</font>

<font weight="900" stylex="italic">Roboto-BlackItalic.ttf</font>

<font weight="700" stylex="normal">Roboto-Bold.ttf</font>

<font weight="700" stylex="italic">Roboto-BoldItalic.ttf</font>

</family>

即使沒有什麼程序員基礎也不難看懂這段代碼的意思,沒錯,font.xml 控制了 Android 操作系統在不同 UI 界面中的字體粗細,告訴系統該在哪些地方分別調用哪一款 Roboto 字體

Roboto 是 Google 為 Android 操作系統設計的一個無襯線字體家族,原本包含 Thin、Light、Regular 、Medium、Bold、Black 共計 6 套字重(即 weight),同時每個字重還有斜體版本(即 italic)。

此外,Roboto 字體家族的部分字重還有窄版的 Condensed 及對應的斜體,它們在 Android 操作系統中通常用作桌面啟動器應用抽屜的圖標標籤,保證在有限的空間內顯示更完整的應用名稱。這種設定同樣在 fonts.xml 這個文件里有所體現。

不難看出,fonts.xml 就像是一本字典,Android 操作系統在需要調用某一個字體效果時就會在這當中進行查詢,然後按圖索驥,找到並調用 system/fonts 下對應的字體文件,最後我們就在界面上看到了字體效果,是不是很簡單?

你每天都在看的中文字體並不完美

我們繼續用這個思路繼續往下看 Android 操作系統中中文字體的調用機制。

在 Android 5.0 和 6.0 版本中,中文字體的控制代碼如下:

<family lang="zh-Hans">

<font weight="400" stylex="normal">NotoSansSC-Regular.otf</font>

</family>

在 Android 7.0 到 8.1 版本中,中文字體的控制代碼變成了這樣:

<family lang="zh-Hans">

<font weight="400" stylex="normal" index="2">NotoSansCJK-Regular.ttc</font>

</family>

而在 Android 9 之後,中文字體的控制代碼改成了這樣:

<family lang="zh-Hans">

<font weight="400" stylex="normal" index="2">NotoSansCJK-Regular.ttc</font>

<font weight="400" stylex="normal" index="2" fallbackFor="serif">NotoSerifCJK-Regular.ttc</font>

</family>

這三套代碼基本大同小異,早期版本調用思源黑體的 OpenType 文件,後來改成了思源黑體的 TrueType Collection 文件,並且用額外的 index 代碼指定了集成字型檔中的文件序號,再後來又追加了缺字回退機制(即思源黑體里沒有的符號用思源宋體來顯示)。

不過仔細觀察和對比後卻不難發現,Google 在中文字體調用機制上偷了懶:和英文、數字字體中使用 6 套不同粗細字體並且還有斜體、窄版等做法不同,中文環境下 Google 僅用了 font weight=400 來敷衍了事

這種區別對待給我們帶來了什麼問題呢?

我們以谷歌原生系統默認的「思源黑體單字重」效果和我優化後的「思源黑體多字重」效果作比較:

默認樣式(左)和優化樣式(右),均為思源黑

上圖中,我們可以看出哪怕中文只有一個「font weight=400」的配置,但界面上依然可以在標題部分顯示粗體,但這個粗體似乎有些問題,我們從上圖中截取兩段,特寫鏡頭對比一下:

偽粗體和真粗體對比

不難發現,系統默認方案下出來的粗體,首先粗度上就有問題——它顯然不夠粗啊!如果你的觀察力不是很強,覺得兩個標題粗度差不多,不妨再觀察一下上圖「大東山谷」和「普洱歌劇貓」這兩個 ID 的字重,差別會更加明顯。

事實上,默認字體的粗體不僅粗度不夠,渲染效果也非常糟糕,這種無中生有冒出來粗體,是 Android 系統自動把字體機械加粗顯示出來的效果,Windows 下也有相似的機制,我稱之為「偽粗體」。「偽粗體」機制會帶來一些很糟糕的體驗,很多手機現在主題商店裡都能換字體了,但只能達到單字重效果,比如這樣:

行黑體,不好意思粗體糊了

阿麗達黑體,粗體筆畫變形

上述這兩個問題的鍋,主要是安卓默認單字重的問題。粗體並不是獨立的字體文件,而是系統自動機械加粗的「偽粗體」。而「偽粗體」由於沒有經過人工較准,難免出現筆畫粘連、字體變形等問題。

PS. 這裡開發者也得背一部分鍋,因為很多時候哪怕我們優化了多字重效果,這些問題還會或多或少遇到。而 App 開發者通常只會在系統自帶的字體下測試,開發的時候也沒嚴格調用多字重,非要用糟糕透頂的「偽粗體」渲染。

借 Magisk 用上多字重字體

解決方法則很簡單——開啟多字重效果,讓粗體單獨使用一個優質的字體文件來顯示。

這不僅能夠解決我們在上面展示的大部分字體問題,除了常規和粗體,還有豐富的其他粗細檔位顯示效果(例如微信聊天界面左上角就應該是 Medium 中粗體)。

微信標題字體

這裡插句題外話。我從 Android 5.0 就開始製作多字重的 Android 字體,那時候只需簡單仿寫谷歌對英文字體的控制方法,然後手動擴展一下缺失的幾個字重文件即可。而 Android 7.0 之後,包括現在的 Android Q,雖然類似的方法可以繼續用,但是得額外多一些 ttc 格式字體的製作成本,不然無法做到真正全局替換,某些頑固的 App 和系統界面還會強制調用 ttc。在這個過程中,我們還不能全都改用 TrueType Collection,因為舊系統只支持 OpenType 和 TrueType。

為了兩全其美,我就繼續在高版本系統用 otf,同時插一段 ttc 的代碼做字體回退。

最終完美兼容 Android 5.0 到 Android Q 通用中文字體解決方案如下:

<family lang="zh-Hans">

<font weight="100" stylex="normal">NotoSansSC-Thin.otf</font>

<font weight="300" stylex="normal">NotoSansSC-Light.otf</font>

<font weight="400" stylex="normal">NotoSansSC-Regular.otf</font>

<font weight="500" stylex="normal">NotoSansSC-Medium.otf</font>

<font weight="700" stylex="normal">NotoSansSC-Bold.otf</font>

</family>

<family lang="zh-Hans">

<font weight="400" stylex="normal" index="2">NotoSansCJK-Regular.ttc</font>

</family>

除了系統原有的 Regular,這套字體調用機制增加了包含 Thin、Light、Medium、Bold 在內的共計 5 套字重,沒有加入 Black 的原因是中文環境基本沒有用到那麼粗的情況。事實上,大多數情況下我們連 Thin 也用不到,只不過我同時還要做 iOS 的字體,蘋果系統的通知中心等 UI 界面需要這個Thin,就一起用了。

早些時候在我公眾號以及極限、知乎等社區有分享過這個方案,現在看很多人的 Magisk 字體模塊也都有我方案的影子。畢竟再怎麼像,文件的命名規則、Android 7.0 之後仍然在用 otf 的奇怪思路、還有中文有 Thin 卻沒有 Bold 的詭異設置,別人不可能和我想得一模一樣。

關於 ttc 格式字體的製作,限於篇幅我就不贅述了。需要涉及到 ttf name 和 Adobe Font Development Kit 及一定的腳本編寫基礎,而補字型檔和修改字型則可以用 font creator、font forge、font lab studio 等工具完成。

到這裡,我們算是完成了 Android 字體調用規則的科普,回顧一下,要想實現完美的中文字體效果,我們至少需要考慮這樣幾個問題:

  1. 想要全局替換多字重的中英文,是不是要手動一個個換進去?
  2. 中文字體的體積很大,手機的系統分區放不下那麼多字重文件怎麼辦?
  3. 每次換字體都要重新換一遍嗎,有沒有一鍵操作?

OK,我們來看下這兩個問題的優先程度。

下圖是我修改完成的思源黑體中文五字重以及 GoogleSans 英文數字 6 字重後,全部 39 個需要替換的文件。他們合計達到了 100MB:

需要替換的素材合計達到了100MB

如果手動替換進系統,文件數量也忒多了一些,使用 TWRP 卡刷勉強能解決這個問題(直接開機狀態用RE管理器覆蓋的話,可能操作到一半系統發現原來的字體文件讀取不到,可能就重啟了,非常不方便)。

另一方面,也並不是所有機型都能額外塞下這 100M 大小的字體文件,我之前用一加 5T 的時候就發現,官方只留了大概 70~80M 的空間,不對系統組件進行精簡的前提下很多字體都刷不進去。於是以上兩個問題就引發了第三個問題:換字體太麻煩了

好在 Magisk 的模塊掛載機制就能解決這所有的問題,而刷入字體模塊幾乎是一鍵完成,不佔多餘的系統分區空間,卻能達到替換系統文件一樣的效果

由於製作 Magisk 模塊字體還會涉及到一些簡單的代碼,有興趣的朋友可以自己研究。我在這裡直接提供一個思源黑體模板,大家可以直接刷入實現多字重效果或按需進行手動修改——按照前文的教程修改 fonts.xml 這個配置並附上 system/fonts 的配套字體文件,即可換上自己想要的字體。

思源黑體5字重+GoogleSans英文6字重Magisk模塊(V2.000)

提取碼:njzy

另外在上面的 Magisk 模塊模板中有一個 module.prop 文件,裡面有兩行關鍵代碼:

id=201812012322

name=思源黑體5字重+GoogleSans英文【寧靜之雨模板】

第一行表示獨一無二的模塊 id,相同 id 的模塊刷入是會覆蓋的,記得修改一下;第二行當然就是模塊顯示的名字了,按需調整即可。

做好 Magisk 字體模塊後,在 Magisk 里刷上字體模塊,勾選重啟即可。唯一的注意事項就是不要同時選多個字體模塊,否則系統會隨機選其中一個生效。另外,有一些模塊的作者也會修改字體配置文件:比如在任意手機上開啟 Google Pixel 手機某些特性的模塊里,作者可能就會加上 Google Sans 字體家族的擴展,這裡就會和我們的字體模塊產生衝突。

安裝 Magisk 字體模塊後我們可以隨意勾選切換,重啟即可生效。完美的多字重擴展且不佔系統空間,靈活方便,這就是選則 Magisk 替換字體的原因!

關聯閱讀:

  • 每個 Android 玩家都不可錯過的神器(一):Magisk 初識與安裝
  • 每個 Android 玩家都不可錯過的神器(二):保留 Magisk 進行「無痛 OTA」
  • 每個 Android 玩家都不可錯過的神器(三):用好 Magisk Manager,騙過特定應用的 root 檢測

推薦閱讀:

TAG:Android |