如果您的手機,已內建其他宋、明、楷體…,建議跳過本文!
關於 Magisk,請參考:https://github.com/topjohnwu/Magisk#introduction

前幾天,試了一下 Android P。發現先前文章中,下列設定預設字型的方法失效了!

fonts.xml, line 22:
<familyset version="23">
    <!-- first font is default -->
    <family name="serif">
        <font weight="400" style="normal">NotoSerif-Regular.ttf</font>
        <font weight="700" style="normal">NotoSerif-Bold.ttf</font>
……

稍微查了下 Source code(我試用的是 LineageOS)發現,它定義了一個 Constant “DEFAULT_FAMILY”:

frameworks_base/graphics/java/android/graphics/Typeface.java, line 156:
private static final String DEFAULT_FAMILY = "sans-serif";
……

它似乎不再遵循“first font is default”,而把 sans-serif 強制設定成預設字型!?

目前大多數更換字型的 app,大多是用置換法。用使用者選擇的字型檔取代內置字型檔,內置字型就此消失。而先前文章的作法,只是在系統內新增字型檔,內置字型依然存在。程式、網頁設計者,依然可以指定使用他們喜歡的英文字型(中文字形是 Fallback 字型,後面會有說明)。但在 Android P 中,這做法似乎不太適合了!sans-serif 英數字,搭配 NotoSerifCJK 中文,感覺很不搭調。

在 Android 系統中,中文字型是 Fallback 字型,無法單獨指定使用。在 fonts.xml 檔案(內容詳頁面 2)內,有 family name 或 alias name 的字型,是一等公民。其他,只有 family lang 的 Fallback 字型,是二等公民。在一等公民內,找不到字型時,才會到二等公民列表內,依語言 (family lang),尋找相應的字型。

在 Android P 以前,一個 family lang 只能有一種字型(除非你用不同 font weight 區分)。如今在 Android P 中,內建了 NotoSerifCJK (思源宋體)字型,fonts.xml 也新增了一個新元素:fallbackFor。

    <family lang="zh-Hant zh-Bopo">
        <font weight="400" style="normal" index="3">NotoSansCJK-Regular.ttc</font>
        <font weight="400" style="normal" index="3" fallbackFor="serif">NotoSerifCJK-Regular.ttc</font>
    </family>

如果 app 中指定用 serif 字型,中文就會用 NotoSerifCJK 字型;否則,用 NotoSansCJK。但問題是,系統預設 sans-serif,絕大多數 app 也選用 sans-serif。所以,NotoSerifCJK 可能只能在少數網站上看到。事實上,現有網站上,用手機能看到明體、宋體、楷體的,多半是用網路字型 (Google Fonts),根本用不到 NotoSerifCJK(本站便是一例)。

幾經思考後,決定也用置換法來改字型吧!

Magisk Module 下載(Magisk v20.4 以前)
Magisk Module 下載(Magisk v20.4(含) 以後)

如果您未使用 Magisk,可以下載上述檔案並解壓縮後,將 system/fonts 目錄內的字型檔,參考先前文章的作法,取代手機上 /system/fonts 內相應的字型檔(建議先備份原始字型檔)。記得檔案權限要修改成 -rw-r–r– 。

ps.
1. 修改後才發現,用網路字型的似乎越來越多了。最後一張圖,又看到了 sans 字型。
2. Typeface.java 程式,在定義 DEFAULT_FAMILY 之前,有一段註解。本文提供的字型檔,都只是更改檔名,未修改 metadata。目前看來沒問題,但不能保證適用於未來的版本。

    // Value for weight and italic. Indicates the value is resolved by font metadata.
    // Must be the same as the C++ constant in core/jni/android/graphics/FontFamily.cpp
    /** @hide */
	private static final String DEFAULT_FAMILY = "sans-serif";

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *