一份給 Android 開發者的字體排印指南
本文搬運自字體博客 Fate/Typo. 譯者 Chao Shell. 譯文鏈接:
一份給 Android 開發者的字體排印指南
原文:The Android Developers Guide to Better Typography
作者:Rod Sheeter時間:2017 年 12 月 6 日譯按:去年更新的 Android Oreo,帶來了 「可下載字體」 的新特性,給予開發者更靈活的字體配置方式,縮減 APK 文件大小和共享字體以環節存儲空間佔用對設備廠商也是利好。Google Design 的這篇文章以一款應用程序——Plaid 為例,介紹了具體的字體排印案例。
字體排印可以使一款應用程序的吸引力和可用性發生重大變化。現在,Android 開發者可以使用 Google Fonts 中的字體,其簡單,高效,並提供了一種新的字體排印方式。
儘管每一位開發者都知道,「設計」在用戶體驗中扮演著重要角色 ,它可能是一款應用成功或失敗的關鍵因素。但在面對推進發布,逃避集成自定義字體的複雜性或是看似神秘的選擇字體的藝術時,還是有著直接使用默認字體的誘惑。
幸運的是,Android Studio 支持新的「可下載的字體」功能,可以更輕鬆地為應用程序構建獨特的字體排版。此功能可以輕鬆地將完整的 Google Fonts 中自由、可靠且高質的字體輕鬆地在 JellyBean 及更高版本(SDK 16+)中自定義字體排印。
除了美學改進之外,「可下載的字體」還可以減小 APK 文件的整體大小,並減少內存佔用,因為已下載的字體將在所有的應用程序之間共享。而因為不需要預先捆綁字體,APK 文件會進一步更減小。如果一個應用程序從 Google Fonts 下載了一款字體,Android 會將其保存在存儲空間中,以便其他應用程序也可以使用它,而無需佔用任何額外的存儲空間。就像我們網站的 API 直接向網站提供字體一樣,人們使用 Google 字體越多,共享的延遲就越大。
在本教程中,我們以示例應用程序為例,通過以 Google Fonts 中的字體替換具有的特性和動態範圍樣式的內容的標準字體,來改善字體排印。我們將使用一款名為 Alegreya 的字體,作為一款「超級字體家族」,其具有廣泛的樣式、字重和變體。這意味著我們將有大量的字體排印的選擇來微調界面外觀。
我們使用的示例應用程序是由 Nick Butcher 開發的 Plaid,這是一款發布 Material Design 相關新聞的可滾動 Feed 應用。這些全出血 (譯註 1) 的圖塊,你可以點擊或點擊以展開進入 dribble 的頁面,其中有「喜歡」和「瀏覽」的統計信息。
本教程面向開發者,但它也解釋了一些決定設計背後的「原因」,因此請注意這兩點!
在我們開始之前
首先安裝 Android Studio 3.0,然後從 Github 中 clone「Plaid」項目並 checkout b76937,這是我們將用於本教程的版本:
git clone https://github.com/rsheeter/plaid.gitcd plaidgit checkout b76937
現在,在 Android Studio 3.0 中打開該項目。
為了使用 Google Fonts 提供程序,你必須安裝 Google Play 服務 12 版以上。如果你正在使用升級到最新系統的設備,則可以跳過; 但如果你使用的是 Android Studio 啟動的模擬器,則可能使用的是舊版 Google Play 服務。從 Android Studio 更新 Android 虛擬設備,請按照下列步驟操作。
1. 創建一個帶有 Play Store 的虛擬設備(Tools > Android > AVD Manager),Play Store 中的圖標表示為:
2. 在 Android Studio 中啟動一個虛擬設備。打開模擬器屏幕右側的「Extended Controls」,點擊垂直按鈕面板底部的「…」圖標:
3. 選擇 Google Play 並檢查版本號。如果您運行的是 11.2 版或更低版本,請點擊 Update 按鈕,這將引導至 Play Store,然後點擊或點擊綠色的 Update 按鈕:
4. 現在已更新至 11.2 或更高版本,該設備將支持可下載的字體。
更新 About 頁面
首先,我們來更新 About 頁面。頁面下半部分的「正文」段落目前被設置為 Roboto Regular,這是一款無襯線字體,頁面上半部分的標題被設置為 Roboto Mono Regular。讓我們將其轉換為襯線字體 Alegreya,這是一種充滿活力的當代設計,其靈感來自書法字母,具有充滿活力和節奏多變的特點。 Alegreya 是一款「超級字體家族」,最初用於文學作品排印,包括襯線和無襯線的姊妹字體家族。
標題文字就像「英雄形象」,這一圖像能將人引導到頁面中。並能定義情感語氣。這裡的標題的字母作為「蒙版」,將薄荷綠的前景切掉,鏤空顯示後面的圖像。從 Roboto Mono Regular 改為 Alegreya Black,將為背景圖像提供更大的鏤空區域,更加明亮。
設置「About Activity」文本
由於「About Activity」文本目前為「default」文本樣式,即 Roboto Regular,我們必須手動設置為另一個:
- 打開 app/src/main/res/layout/about_plaid.xml
- 選擇 Design 面板
- 在 Component Tree 面板中, 打開 about_description
- 在 Attributes 面板中, 打開 fontFamily 下拉列表並選擇 More Fonts… (你可能需要點擊 View all attributes才能看到 fontFamily)
- 選擇字體家族 Alegreya
- 選擇字體樣式 Regular
Android Studio 已經配置了我們的應用程序以從 Google Fonts「提供程序」中檢索字體。為此,它對我們的源碼樹進行了一些更改:
app/src/main/res/font/ (查看更多)
這個新目錄包含描述字體資源的 XML 文件。在這種情況下,它提供了從 Google Fonts 提供程序載入字體的說明。
app/src/main/res/values/font_certs.xml (查看更多)
為確保字體請求僅由可信方回應,該文件指定字體提供程序的簽名。
app/src/main/res/values/preloaded_fonts.xml (查看更多)
這是在安裝和更新過程中載入的字體列表,以確保這些字體在啟動應用程序時可用。
你可以在 commit a1e711c 中看到此步驟的示例 diff。
更新裁剪文本視圖
文本樣式目前是 Roboto Mono Regular。讓我們繼續上一步的更改:
7. 在 Design 視圖中, 選擇「CutoutTextView」
8. 打開「fontFamily」下拉菜單並選擇「More Fonts…」
9. 選擇字體家族「Alegreya」
10. 選擇字體樣式「Black」
11.(對於步驟 11, 請見下文)
如果你現在嘗試此操作,字體仍然是 Roboto Regular,而不是 Alegreya Black,原因是默認情況下,聲明性字體是非同步獲取的(了解更多)。完成之後,系統將嘗試使用 setTypeface 更新 TextView 的字體,但這會因 CutoutTextView 不會擴展 TextView 而失敗。
但是,CutoutTextView 並沒有實現 fontFamily 屬性(這裡)。如果我們將字體提取標記為 blocking,那麼 fontFamily 將在我們請求時做好準備。如果我們不將其標記為 blocking,那麼為 fontFamily 返回的值將不可用。(我們也可以編寫自己的非同步獲取,但我們稍後再談。)
- 打開 app/src/main/res/font/alegreya.xml 和 alegreya-black.xml,然後將此屬性追加到 <font-family> 元素的末尾:
app:fontProviderFetchStrategy="blocking"
現在試試吧!(你可以在 commit f1c997 看到此步驟的示例 diff)
更新 text-size
看看「About」文本,它在灰色背景上略顯灰色。 Alegreya 是一款襯線字體,具有較高的「筆畫差異(stroke modulation)」 (譯註2),意味著字母從最粗到最細的字體都有很大的不同。這導致總體視覺對比度較低。字體中的細微變化可能會使其看起來模糊,尤其是在小字型大小的情況下。
為了緩解這個問題,我們將這個段落的 text-size 從 16sp 增加到 18sp。這將增加文本與其背景的明顯對比。
about_plaid.xml 的 TextView 使用 TextAppearance.About 樣式。要將文本大小從 16sp 更改為 18sp,可編輯 app/src/main/res/values/styles.xml 這一部分:
<style name="TextAppearance.About" parent="@android:style/TextAppearance.Material.Body1"> ...- <item name="android:textSize">16sp</item>+ <item name="android:textSize">18sp</item> </style>
你可以在 github.com/rsheeter/plaid/commit/4dda25 上看到此步驟的示例 diff。
更新應用標題
接下來,我們將通過編程方式提取字體,以更改我們的應用程序的標題。標題目前為應用了「小型大寫字母」的 OpenType 特性的 Roboto。我們還使用了額外的「tracking」來分隔這些字母。
(這個細節是借鑒了書籍排印的慣例,章節標題常位於頁面的頂部並採用小型大寫字母。了解更多關於字體排印的信息,可查閱 Jan Middendorp 的《Shaping Text》一書。)
非同步獲取會因 Toolbar 不是 TextView 而失敗,就像 CutoutTextView 不是 TextView 一樣。另外,Toolbar 無法實現 fontFamily 屬性,所以我們不能只設置 blocking 來修復。
相應的,我們可以嘗試以編程方式獲取和賦值字體。 在 app/src/main/java/io/plaidapp/ui/HomeActivity.java 中使用 FontsContractCompat (參考) 按照以下四個步驟請求字體。
1. 我們需要一個線程等待字體,聲明一個變數以保存:
private Handler fontHandler
2. 添加一個 Method 來管理字體處理線程:
private Handler getFontHandlerThread() { if (fontHandler == null) { HandlerThread handlerThread = new HandlerThread("fonts"); handlerThread.start(); fontHandler = new Handler(handlerThread.getLooper()); } return fontHandler;}
3. 添加一個 Method 將 Typeface (參考 ) 應用於 Toolbar:
private void styleToolbar(Typeface typeface) { // this is gross but toolbar doesnt expose its children for (int i = 0; i < toolbar.getChildCount(); i++) { View rawView = toolbar.getChildAt(i); if (!(rawView instanceof TextView)) { continue; }TextView textView = (TextView) rawView; textView.setTypeface(typeface); }}
4. 在 onCreate 中,從字體提供程序啟動非同步獲取:
@Overrideprotected void onCreate(Bundle savedInstanceState) { ... FontRequest fontRequest = new FontRequest("com.google.android.gms.fonts", "com.google.android.gms", "name=Alegreya", R.array.com_google_android_gms_fonts_certs); FontsContractCompat.FontRequestCallback toolbarFontCallback = new FontsContractCompat.FontRequestCallback() { @Override public void onTypefaceRetrieved(Typeface typeface) { // If we got our font apply it to the toolbar styleToolbar(typeface); } @Override public void onTypefaceRequestFailed(int reason) { Log.w(TAG, "Failed to fetch Toolbar font: " + reason); } }; // Start async fetch on the handler thread FontsContractCompat.requestFont(this, fontRequest, toolbarFontCallback, getFontHandlerThread());
切換到 Alegreya Sans SC Black
回到主頁面,我們注意到標題看起來有點過於細。像許多襯線字體一樣,Alegreya 的筆畫差異導致視覺對比度較低,尤其是當與無襯線字體相比時。
幸運的是,Alegreya 是一款「超級字體家族」,其襯線和無襯線樣式都有多種字重,適配這兩種樣式的字體並使用不同的字重來構建界面,以內容描繪 UI。讓我們試試 Alegreya Sans Small Caps (SC) 吧。
Alegreya 的小型大寫字母本身就較小,但我們可以通過增加其字重來改善這一點。試試 Black (900) 的字重。
1. 複製 res/font/alegreya.xml 以創建 res/font/font/alegreya_sans_sc_black.xml
2. 編輯 alegreya_sans_sc_black.xml 以更改 app:fontProviderQuery 為 name=Alegreya Sans SC&weight=900
3. 編輯 res/values/preloaded_fonts.xml 以添加新字體:
4. 在 HomeActivity.java 中指定新的 query:
FontRequest fontRequest = new FontRequest("com.google.android.gms.fonts", "com.google.android.gms", "name=Alegreya Sans SC&weight=900", R.array.com_google_android_gms_fonts_certs);
將 Alegreya Black 更改為 Bold
再來看看主頁上的標題
Black 字重在這裡有點太強烈了,所以讓我們把它降為 Bold (700)。
1. 將 alegreya_sans_sc_black.xml 重命名為 alegreya_sans_sc_bold.xml 並編輯以更改 app:fontProviderQuery 為 name=Alegreya Sans SC&weight=700
2. 在 HomeActivity.java 中更新 query:
FontRequest fontRequest = new FontRequest("com.google.android.gms.fonts", "com.google.android.gms",- "name=Alegreya Sans SC&weight=900",+ "name=Alegreya Sans SC&weight=700", R.array.com_google_android_gms_fonts_certs);
您可以在 commit ac55478 處看到應用程序最終狀態的示例 diff(使用了 Alegreya Sans SC Bold)。看看項目的比較吧。
更新 Dribble 視圖
要進入應用程序中的「dribble」視圖,請點擊或單擊主屏幕上的卡片。再一次的,我們用 Alegreya Black 替換 Roboto Mono Regular。
在 app/src/main/res/layout/dribbble_shot_title.xml 中,請注意標題和描述在使用 @style/TextAppearance.DribbbleShotTitle 和 @style/TextAppearance.DribbbleShotDescription 設置樣式。在 app/src/main/res/values/styles.xml 中找到它們(提示:Ctrl+點擊)。現在改變字體:
- <item name="android:fontFamily">monospace</item>+ <item name="android:fontFamily">@font/alegreya_black</item>
你可以在 commit 0e53b56 查看示例 diff。
更改數字樣式
「dribble」的視圖還有一點需要改進。
「喜歡」和「瀏覽」按鈕使用了所謂的「舊式數字」。這一設計是為了與文本段落中的小寫拉丁字母混排。但是,對於舊式數字本身而言,看起來不合適,因為他們的降部 (譯註 3) 有時會掛在其他文本的基線 (譯註 4)之下。
相應的,我們使用 lnum 特性。這告訴應用程序使用「齊線數字」,因為它們被設計為與大寫字母相同的高度,所以更加易讀。(了解更多內容,查看 Typekit)
通過查看 app/src/main/res/layout/dribbble_shot_description.xml,我們可以看到,「喜歡」和「瀏覽」計數器的樣式是 @style/Widget.Plaid.InlineActionButton。
在 app/src/main/res/values/styles.xml 中找到 @style/Widget.Plaid.InlineActionButton(提示:Ctrl+點擊)。
現在添加一條指令來為這些計數器使用齊線數字:
<style name="Widget.Plaid.InlineActionButton" parent="@android:style/Widget.Material.Button"> <item name="android:gravity">center_horizontal</item> <item name="android:textAppearance">@style/TextAppearance.CommentAuthor</item> <item name="android:drawablePadding">@dimen/spacing_micro</item> <item name="android:background">?android:selectableItemBackgroundBorderless</item>+ <item name="android:fontFeatureSettings">lnum</item></style>
您可以在 commit 4dda25 看到一個示例 diff。
結論
經過這些簡單的更改後,並藉助了 Google 的免費開源字體庫, 我 fork 的 Plaid 應用程序 現在具有了更醒目和更具功能性的字體排印。通過 Android 新的可下載字體功能,你可以使用 Google Fonts 中的任何字體來自定義應用中的字體排印。正如本教程所述,只需進行一些更改,就可以在易讀性和用戶體驗方面帶來真正的改變。希望對你有所幫助!
(譯)註:
- 全出血:出血為印刷出版專有名詞,指在列印中超出紙張裁剪的邊緣部分,也就是需要裁剪的區域。這裡的全出血意思是作品圖塊與屏幕邊緣之間沒有空隙。
- 筆畫差異(stroke modulation):difference in stroke width within a letterform; also called stroke modulation. 字形內部筆畫寬度的差異,亦稱作「contrast」。
- 降部:descender,如 g、j、p、q、y 從基線向下延伸的部分。
- 基線:baseline,貼著如大寫字母「A」和小寫字母「b」下部的那一條「線」
推薦閱讀:
TAG:字體排印 | Android開發 | 質感設計MaterialDesign |