第16 章
使用客製化字型與動態型態
當你加入標籤至視圖中,Xcode 可以讓你使用屬性檢閱器改變字型,這裏你可以從預設字型集中挑選系統字型,或客製化字型。
倘若你在預設字型集中沒有找到任何適合你 App的字型該怎麼做?字型學(typography)是 App 設計的一個重要觀念。使用合適的字型可以讓你的 App 更有質感,你有可能會想要使用一些由第三方所建立,沒有內建在 Mac OS 的客製化字型。只要在 Google 簡單搜尋,你會發現有許多幫 App 開發的免費字型。問題是該如何在你的 Xcode 專案中將字型包進你的 Xcode 專案中?你可能想說我們只要將字型檔直接加入專案中就可以,但不只這樣,本章將會逐步告訴你該怎麼加入新字型。
通常,我們將建立一個範例 App 來示範。這個範例 App 非常簡單。它只是顯示一組不同自訂字型的標籤。
你可以從頭建立這個範例,或者至 http://www.appcoda.com/resources/swift6/CustomFontStarter.zip 下載專案模板。
下載自訂的字型
我們會使用幾個可以免費使用的字型。不過,我們不能透過我們的專案模板綁定與發佈它們。在開始之前,從以下的連結下載字型:
- https://www.fontsquirrel.com/fonts/mohave
- https://www.wfonts.com/font/hallo-sans
- http://fontfabric.com/canter-free-font/
另外,你也可以在專案中使用你自己的字型。或者你也可以在這些網站找到一些漂亮的字型:
- 100 Greatest Free Fonts Collection https://speckyboy.com/best-free-fonts/
- The 100 best free fonts http://www.creativebloq.com/graphic-design-tips/best-free-fonts-for-designers-1233380
- A Curated Collection of the 40 Best Google Fonts https://www.typewolf.com/google-fonts
- 100 Greatest Free Fonts for 2022 https://graphicdesignjunction.com/2022/01/100-greatest-free-fonts-for-2022/
- FontPair https://fontpair.co
- 82 best free fonts for designers http://www.creativebloq.com/graphic-design-tips/best-free-fonts-for-designers-1233380
加入字型檔至專案中
與其他資源檔一樣(例如 image),你必須先加入字型檔至你的 Xcode 專案中。我想要將所有的資源檔放進 font 資料夾中,至專案導覽器中,在 CustomFont 資料夾上點擊右鍵,並選取 New Group 來建立資料夾。變更其名稱為 font ,然後拖曳你剛下載的字型,並把它們加進該資料夾中。

當 Xcode 提示你進行確認時,請確保勾選你的目標(例如:CustomFont),並選擇 Copy files to destination 選項。這會指示 Xcode 將字體文件複製到你的應用程式資料夾中。

這些字形檔通常是 .ttf 或 .otf 格式。一旦你將所有的檔案加進去後,你便會在專案導覽器下的 font 資料夾中找到它。

在專案 info 設定中註冊字型
使用字型之前,你必須在專案設定中進行註冊。在專案導覽器中選擇 Info
plist,加入一個新的屬性,名為 Fonts provided by application。這是一個可以讓你註冊自訂字型檔的陣列 key。
在這些 key 中按右鍵並從內容選單中選取 Add Row。從下拉式選單中滑動來選取 Fonts provided by application。點擊揭示圖示(也就是三角形圖示)來展開 key。你應該會見到 Item 0。點兩下 Value 欄位,輸入 Hallo sans black.otf 。然後在 Item 0 旁邊點擊 +
按鈕來加入另一個字型檔。重複相同的步驟直到所有的字型都註冊完成。最後的結果如以下的截圖所示。確定你有正確地輸入相同的檔名。否則你將無法使用這個字型。

在介面建構器使用自訂字型
當你加入字型字你的專案中後,Xcode 可以讓你在介面建構器預覽字型。 任何你加入專案中的字型,都可以在介面建構器中看到。可以在屬性檢閱器中改變物件的字型(例如標籤),而介面建構器便會立即渲染其結果。

在程式中使用自訂字型
另外你也可以透過程式來使用自訂字型,只要以你喜愛的字型來實例化一個 UIFont
物件,並將其指定給一個 UI 物件,例如 UILabel
。以下面的範本為例:
label1.font = UIFont(name: "Mohave-Italic", size: 25.0)
label2.font = UIFont(name: "Hallo sans", size: 30.0)
label3.font = UIFont(name: "Canter Light", size: 35.0)
倘若你將以上的程式放進 ViewController
類別的 viewDidLoad
方法中,並執行 App,所有的標籤應該都能夠跟著變更為所指定的字型。
對於初學者,你可能會有所疑問:你要如何知道字型的名稱呢? 字型名稱似乎跟檔案名稱不一樣對吧?
很好的觀察力,當初始化一個 UIFont
物件時,你應該指定字型名稱而非字型的檔案名稱。要找到字型名稱,你可以在 Finder 的字形檔案上按下右鍵,並從選單中選取簡介(Get Info)。在全名(Full Name)欄位顯示的值就是在 UIFont 中所用到的字型名稱。例如在範例的截圖中,字型名稱是 Canter Light。

動態型態的運用
動態型態(Dynamic Type)不是新的技術。自從 iOS 7 就已經開始導入。有了動態型態,使用者能夠選取他們自己的字型,只要 App 有支援動態型態即可。

至目前為止,所有的標籤都是固定字型。即使你至 設定 > 一般 > 輔助使用 ,並起用放大文字,你也不能放大範例 App 的字體。
啟用動態型態
要讓你的 App 能夠支援動態型態,你必須要設定標籤的字型為文字樣式( Text Style),不是設為特定字型。跟我們之前所做的一樣,你可以透過介面建構器或使用程式來變更文字樣式。如果你至 Main
storyboard,選取其中一個標籤,你可以在屬性檢閱器來變更它的字型。這裡我們不使用自訂字型,選擇 Text Style(譬如說,Title 1)。

如果你比較喜歡以程式來做設定,將 ViewController.swift
的 viewDidLoad()
方法中的程式以下面程式取代:
override func viewDidLoad() {
super.viewDidLoad()
label1.font = UIFont.preferredFont(forTextStyle: .title1)
label2.font = UIFont.preferredFont(forTextStyle: .headline)
label3.font = UIFont.preferredFont(forTextStyle: .subheadline)
}
這裡 UIFont
的 preferredFont
方法接收以下其中一種文字樣式:
.largeTitle
.title1
,.title2
,.title3
.caption1
,.caption2
.headline
.subheadline
.body
.callout
.footnote
現在開啟模擬器,並置「設定」來啟用「放大文字」(如圖 16.7)。設置完成之後,執行 App 來看一下,你將會看到標籤已經放大。

自動調整字體
如果你回到設定並調整成想要的字體大小,然後重新開啟範例 App,文字的大小沒有改變,現在字的大小在 App啟動後,保持不動。
如何能夠讓使用者在設定中變更字體大小時, App 也能夠啟用字體大小的調整呢?
如果你使用介面建構器,選取標籤,並至屬性檢閱器。勾選 Automatically Adjusts Font 前的核選框。這個標籤現在能夠自動依據字體大小來調整尺寸了。

另外,你可以設定標籤物件的 adjustsFontForContentSizeCategory
屬性為 true
,如此才能確保標籤會因應文字大小的變更。
label1.adjustsFontForContentSizeCategory = true
label2.adjustsFontForContentSizeCategory = true
label3.adjustsFontForContentSizeCategory = true
文字樣式使用自訂字型
任一個文字樣式的預設字型是為 San Francisco,也就是 iOS 系統字型。如果要改成自訂字型該怎麼做呢?如何使用你自己的字型,並同時運用動態型態呢?
在 iOS 11(或以上),開發者現在可以一個稱作UIFontMetrics
的類別,在採用動態型態時也能縮放任何自訂字型。在進一步解釋什麼是 UIFontMetrics
,以及如何使用它時,我們先想一下,當針對動態型態使用一個自訂字型(譬如說,Mohave)時,需要定義什麼。
很明顯,你必須要訂定義每一個文字樣式的字體大小。譬如說,.body
文字樣式其字體大小應該有 15 點,.headline
文字樣式是 18 點...等等。
記得這只是針對預設內容尺寸(content size ),你必須要針對不同種類的內容尺寸提供這些文字樣式的字體大小。你知道 iOS 提供多少種類的內容尺寸嗎?
回到圖 16.7 來數一下。
如果沒有數錯的話,總共有12種內容尺寸。結合 11 種文字樣式,為了支援動態型態,你總共需要132 種不同字體大小(12種內容尺寸x11種文字樣式)。這太複雜了吧!
因此 UIFontMetrics
就是用來協助你定義這些所有字體指標(font metrics)以節省時間的類別。除了自己定義字體指標以外,這個新類別可以讓你取得特定文字樣式的字體指標。然後你可以重新使用這些指標來縮放自訂字型。以下是針對 .title1
文字樣式來縮放一個自訂字型的用法:
if let customFont = UIFont(name: "Mohave-Italic", size: 28.0) {
let fontMetrics = UIFontMetrics(forTextStyle: .title1)
label.font = fontMetrics.scaledFont(for: customFont)
}
你現在可以使用下面的程式來修改 viewDidLoad()
方法:
override func viewDidLoad() {
super.viewDidLoad()
if let customFont1 = UIFont(name: "Mohave-Italic", size: 28.0) {
let fontMetrics = UIFontMetrics(forTextStyle: .title1)
label1.font = fontMetrics.scaledFont(for: customFont1)
}
if let customFont2 = UIFont(name: "Hallo sans", size: 20.0) {
let fontMetrics = UIFontMetrics(forTextStyle: .headline)
label2.font = fontMetrics.scaledFont(for: customFont2)
}
if let customFont3 = UIFont(name: "Canter-Light", size: 17.0) {
let fontMetrics = UIFontMetrics(forTextStyle: .subheadline)
label3.font = fontMetrics.scaledFont(for: customFont3)
}
label1.adjustsFontForContentSizeCategory = true
label2.adjustsFontForContentSizeCategory = true
label3.adjustsFontForContentSizeCategory = true
}
這是你如何使用自訂字型並讓它能夠適應動態型態的方式。執行 App 並快速測試一下。另外,記得在設定調整字體大小,來看看這些文字大小的變化。

在以上的程式中,我們以預設字體大小初始化自訂字型物件,你可以自行決定在預設內容尺寸中的這個字體大小。不過,你可以參考 Apple 的預設字型。
針對 San Francisco 字型,Apple 在 iOS Human Interface Guidelines 公布了它用在不同種內容尺寸的字體指標。圖 16.12 列出在 Large 內容尺寸時所有文字樣式的字體大小

本章小結
Apple 花了很大的力氣來鼓勵工程師使用動態型態。藉由UIFontMetrics
的導入,你現在可以縮放自訂字型,並且讓它們能支援動態型態。在開發你的 App 時,記得會接觸到許多不同的使用者。一些使用者偏好小字體,一些使用者則為了能夠讓閱讀更舒服,偏好大的字體。如果你的 App 尚未使用動態型態,是時候將它加入你的待辦清單中了。
本文摘自《iOS 18 App程式設計進階攻略》一書。如果你想繼續閱讀和下載完整程式碼,你可以從AppCoda網站購買完整電子版,全書範例檔皆可下載。