現在你應該對於 SwiftUI 有了基本概念,並了解如何顯示文字內容,本章我們來看如何顯示圖片。我們也會學習標籤(Label)的用法。
除了文字之外,圖片是 iOS App 開發的另外一個基本元件。SwiftUI 提供一個名為 Image
的視圖,來讓開發者將圖片渲染在螢幕上。首前一章的內容相似,我會建立一個簡單的 App,以示範如何進行圖片的處理。本章可歸納為以下幾個主題:
ignoresSafeArea
來顯示一個全螢幕的圖片? 首先,開啟Xcode 並使用「App」模板( 在 iOS 分類下),來建立一個新專案。輸入專案的名稱,並設定為「SwiftUIImage」。關於組織名稱,你可以設定為你自己公司或組織名稱, 同樣的,我使用「com.appcoda」,但你可以使用自己的值。要使用SwiftUI 的話,請確認在「User Interface」選項中選取 「SwiftUI」然後點擊「Next」,選取要建立專案的資料夾, 如圖 3.1 所示。
專案儲存完成之後,Xcode 即會載入 ContentView.swift
檔,並顯示一個「設計/ 預覽」畫布,如圖 3.2 所示。
超過 4,000 個可設定的標誌,SF Symbols 無縫整合了 Apple 平台的 San Francisco 系統字型,每一個標誌皆設定了不同的權重與比例,可以自動對齊文字標籤,並支援動態型態(Dynamic type)與粗體字(Bold Text)輔助功能,你也可以輸出這些文字,以向量圖形編輯工具來進一步編輯,建立具有共享特點與可用性的自訂標誌。SF Symbols 4 加入 700 多個新符號、增強的顏色自定義、新的檢查器以及對自定義符號的改進支持。
在教你如何在螢幕顯示圖片之前,我們先談一下關於圖片的來源。當然,你可以在 App 中提供自己的圖片。從 iOS 13 開始,Apple 導入名為「SF Symbols」的大量系統圖片,可以讓開發者在任何 App 中使用。iOS 16 進一步修改版釋出了 SF Symbol 4 ,新增了 700 個標誌,並增強的顏色設置。
這些圖片是作為標誌用,由於它整合了內建的 San Francisco 字型,因此使用這些標誌, 並不需要額外的安裝,只要你的 App 是部署在執行 iOS 13(或之後的版本)的裝置,你就可以直接取得這些標誌。但你要注意,現在有五組不同的符號需要考慮:
當要使用這些標誌時,你需要準備的是找到標誌名稱。由於有超過 5,000 個符號可供使用,Apple 釋出一個名為 SF Symbols (https://developer.apple.com/sf-symbols/) 個標誌可以讓你使用,因此你可以很容易地找到你要的標誌來配合你的設計。我極力推薦你在進行下一節之前,先安裝這個 App。
想要在螢幕上顯示系統圖片的話,你可以初始化一個 Image
視圖,加上 systemName
參數,如下所示:
Image(systemName: "cloud.heavyrain")
這將會建立一個圖片視圖,並載入指定的系統圖片。如前所述,SF Symbols 與 San Francisco 字型無縫整合。你可以很容易地應用 font
修飾器來進行圖片的縮放。
Image(systemName: "cloud.heavyrain")
.font(.system(size: 100))
你可以變更字型大小來觀察圖片的反應,如圖 3.4 所示。
同樣的,因為系統圖片實際上是一個字型,你可以應用其他的修飾器如之前所學過的 foregroundColor
,來變更它的外觀。
例如:要變更顏色為藍色,你可以撰寫程式如下:
Image(systemName: "cloud.heavyrain")
.font(.system(size: 100))
.foregroundStyle(.blue)
要加入一個下拉式陰影效果(drop shadow effect ),你只需要使用 shadow
修飾器:
Image(systemName: "cloud.heavyrain")
.font(.system(size: 100))
.foregroundStyle(.blue)
.shadow(color: .gray, radius: 10, x: 0, y: 10)
在前面,我們使用了Apple 內建的圖片。不過,你可能會在App 中使用自己的圖片。那麼,要如何使用 Image
視圖來載入圖片呢?
Note: 你可以任意使用自己的圖片,若是你沒有合適的圖片,也可以至 unsplash.com 下載圖片 (https://unsplash.com/photos/Q0-fOL2nqZc) ,以方便繼續後面的內容。圖片下載完成之後,請將檔名改成「paris.jpg」。
在你的專案能夠使用圖片之前,首先你必須先將圖片匯入素材目錄( Asset Catalog ), 也就是 Assets
。假設你已經準備好圖片(paris.jpg ),按下 command+0 鍵來開啟專案導覽器(Project Navigator ),並選取 Assets。現在開啟 Finder,並將圖片拖曳至大綱視圖(Outline View ),如圖 3.5 所示。
如果你是 iOS App 開發新手,這個素材目錄是你儲存應用程式資源如圖片、顏色與資料的地方。當你將圖片放入素材目錄時,你可以參照它的名稱來下載圖片。另外,你可以設定要載入圖片的裝置(例如:只限 iPhone )。
要在螢幕上顯示圖片,可撰寫程式如下:
Image("paris")
你只需要指定圖片名稱,可在預覽畫布中見到圖片。然而,由於圖片是高解析度圖片( 4437×6656 像素),你只能見到部分圖片,如圖 3.6 所示。
那麼,如何調整圖片呢?你可以使用 resizable
修飾器,如下所示:
Image("paris")
.resizable()
預設上,圖片大小調整是使用「延伸」(stretch )模式。這表示原始圖片將會被放大到填滿整個螢幕畫面(除了頂部與底部區域之外),如圖 3.7 所示。
技術上而言,這個圖片填滿了整個 iOS 所定義的安全區域(Safe Area )。安全區域的觀念已經存在一段頗長的時間了,定義為安全佈局UI 元件的視圖區域。舉例而言,如圖 3.7 所示,這個安全區域不包含頂部列(Top Bar )(也就是狀態列)與底部列(Bottom Bar ) 的區域。安全區域可以避免你不小心隱藏了系統 UI 元件,例如:狀態列(Status Bar )、導覽列(Navigation Bar )與標籤列(Tab Bar )。
既然我們正好說到這件事, 若是你想要顯示全螢幕圖片, 你可以設定 ignoringSafeArea
修飾器來忽略安全區域,如圖 3.8 所示。
你可以針對特定的邊緣來忽略安全區域,例如:要忽略底部邊緣的安全區域,你只要傳送 .bottom
作為參數即可:
.ignoresSafeArea(.container, edges: .bottom)
如果你看一下前一小節這兩張圖片,並與原來的做比對,你應該會發現長寬比(aspect ratio )有些失真。這個延伸模式不會去管圖片的長寬比,它只是將每一邊延伸來填滿安全區域而已。如圖 3.9 所示,要保持原來的長寬比的話,你可以像這樣應用 scaledToFit
修飾器:
Image("paris")
.resizable()
.scaledToFit()
另外,你可以使用 aspectRatio
修飾器,並設定內容模式(Content Mode)為. fit
,這會達成同樣的結果。
Image("paris")
.resizable()
.aspectRatio(contentMode: .fit)
在某些情況下,你想要圖片的長寬比保持一樣,但儘可能地延伸,則你可以應用 .fill
內容模式:
Image("paris")
.resizable()
.aspectRatio(contentMode: .fill)
我們試著來限制圖片的大小,這有助於你對這兩種模式能更了解。frame 修飾器可以讓你控制視圖的大小。舉例而言,設定框架(frame )的寬度為「300 點」,圖片的寬度將會限制在 300 點,如圖 3.10 所示。
現在將 Image
程式以下面的程式碼取代:
Image("paris")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 300)
這張圖片會被縮小,但是仍保持原始長寬比。如果你變更內容模式為 .fill
,圖片看起來與圖 3.7 幾乎相同,然而當你使用selectable 模式並仔細看圖 3.11,長寬比是維持不變的。
你可能會注意到圖片的寬度不是我們想要的,它依然占滿整個螢幕寬度。要正確運作的話,你必須使用 clipped
修飾器來消除視圖額外的部分,如圖 3.12 所示。
除了將圖片裁切為長方形之外,SwiftUI 提供其他修飾器來讓你將圖片裁成不同的形狀,例如:圓形。舉例而言,如果你想要建立圓形圖片,你可以像這樣使用 clipShape
修飾器:
Image("paris")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 300)
.clipShape(Circle())
另外,你可以使用 .circle
代替 Circle()
:
Image("paris")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 300)
.clipShape(.circle)
這裡我們指定將圖片裁成圓形。你可以傳送不同參數(如 Ellipse() )來建立不同形狀的圖片,圖 3.13 為一些範例。
SwiftUI 內建了名為 opacity
的修飾器,你可以使用這個修飾器來控制圖片(或者任何視圖)的不透明度。你傳送一個介於0 與1 的值來指定圖片的不透明度。這裡,「0」代表視圖完全透明,「1」則代表完全不透明。
舉例而言,如果你對圖片視圖應用了opacity
修飾器,並設定其值為「0.5」,則這個圖片將會呈現半透明(partially transparent ),如圖 3.14 所示。
在設計App 時,有時你需要將另一個圖片或文字分層放置在圖片視圖之上。SwiftUI 框架提供一個名為「overlay」的修飾器給開發者,來將圖片進行重疊(Overlay ),例如:你要重疊一個系統圖片(如 heart.fill )至目前的圖片,你可以撰寫程式如下:
Image("paris")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 300)
.clipShape(.circle)
.overlay(
Image(systemName: "heart.fill")
.font(.system(size: 50))
.foregroundColor(.black)
.opacity(0.5)
)
程式中的 .overlay
修飾器帶入一個 View
作為參數。在上列的程式中,我們建立其他的圖片(如 heart.fill ),並將其重疊在目前圖片(如 Paris )之上,如圖 3.15 所示。
事實上,你可以採用任何視圖來做重疊。例如:你可以重疊一個 Text
視圖在圖片之上。程式寫法如下:
Image("paris")
.resizable()
.aspectRatio(contentMode: .fit)
.overlay(
Text("If you are lucky enough to have lived in Paris as a young man, then wherever you go for the rest of your life it stays with you, for Paris is a moveable feast.\n\n- Ernest Hemingway")
.fontWeight(.heavy)
.font(.system(.headline, design: .rounded))
.foregroundStyle(.white)
.padding()
.background(Color.black)
.cornerRadius(10)
.opacity(0.8)
.padding(),
alignment: .top
)
在 overlay
修飾器,你只需要建立一個 Text
視圖,而這個文字視圖將會作為圖片上的重疊物件。我相信你已經熟悉了 Text
視圖的修飾器,我們在前面的章節已經有介紹過。我們只是變更字型與顏色,除此之外,我們加入了間距與背景顏色。另外,要特別說明的是 alignment
參數,對於 overlay
修飾器,你可以提供一個可選值(Optional Value )來調整視圖的對齊。預設是置中對齊,這裡我們想要將文字重疊於圖片之上,如圖 3.16 所示。你可以自己將值變更為「.center」或者「.bottom」,來看看結果為何。
你不止可以重疊圖片或文字在另一張圖片上,你也可以應用重疊來使圖片變暗。將 Image
程式以下列程式替代,並看一下效果:
Image("paris")
.resizable()
.aspectRatio(contentMode: .fit)
.overlay(
Rectangle()
.foregroundStyle(.black)
.opacity(0.4)
)
我們在圖片上畫一個矩形(Rectangle ),並將其前景色設定為「black」。為了達到變暗(darken )效果,我們設定不透明度為「0.4」,也就是 40% 的不透明度,圖片現在應該變暗了。
也可以將程式重寫如下完成一樣的效果:
Image("paris")
.resizable()
.aspectRatio(contentMode: .fit)
.overlay(
Color.black
.opacity(0.4)
)
在 SwiftUI,正好 Color
也是一個視圖,因此我們可以使用 Color.black
作為上層來將下層的圖片變暗。
當你想要將一些亮色文字重疊在太亮的圖片上時,這個技術尤其有用。我們將 Image
程式替換如下:
Image("paris")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 300)
.overlay(
Color.black
.opacity(0.4)
.overlay(
Text("Paris")
.font(.largeTitle)
.fontWeight(.black)
.foregroundStyle(.white)
.frame(width: 200)
)
)
如前所述,這個 overlay
修飾器不限於 Image
,你也可以將它應用在其他視圖上。在上列的程式中,我們使用「Color.black」來使圖片變暗。此外,我們也重疊並放置了一個 Text
。如果你的步驟都正確的話,你應該會見到一個「Paris」的文字放置在深色的圖片上面,如圖 3.17 所示。
自 iOS 15 推出後,SF Symbols 提供四種渲染模式,可以將顏色應用於符號。 根據所選擇的模式,你可以為符號填上單色或多種顏色。 例如,cloud.sun.rain 是一個支持Palette Rendering 的符號。 你可以對符號應用兩種或多種對比色。 下圖顯示如何使用 SF Symbols 應用程式測試調色板。
在 SwiftUI 中,你可以加入 symbolRenderingMode
修飾器來更改模式。 要建立具有多種顏色的相同符號,你可以編寫如下程式碼:
Image(systemName: "square.and.arrow.down")
.symbolRenderingMode(.palette)
.foregroundStyle(.indigo, .yellow, .gray)
.font(.system(size: 200))
我們在程式碼中指定使用palette
模式,然後使用foregroundStyle
修飾器使用顏色。
自 iOS 16 開始,SF Symbols 添加了一個名為 Variable Color 的新功能。 你可以通過更改百分比值來調整符號的顏色。 這在使用某些符號表示進度時特別有用。
你可以下載 SF Symbols 4 (https://developer.apple.com/sf-symbols/) 以試用此新功能。 安裝應用程式後,選擇 Variable 類別並選擇其中一個符號。 在檢查器中,你可以選取 Variable Color 按鈕來啟用該功能。 當你更改百分比值時,符號會對更改做出反應並填充其中的一部分。 以 slowmo
符號為例。 當你將百分比值設置為 60%
時,僅填充一些條形以表示進度。
可變顏色適用於 SF Symbols 內的每種渲染模式(Rendering mode)。 你可以試試更改為其他渲染模式以查看效果。
至於,要在程式碼中設置百分比值,你可以在建立 Image
視圖時,加入 variableValue
參數並將其與百分比值一起傳遞:
Image(systemName: "slowmo", variableValue: 0.6)
.symbolRenderingMode(.palette)
.foregroundStyle(.indigo)
.font(.largeTitle)
在本章中,我介紹了如何以 SwiftUI 處理圖片。SwiftUI 已經讓開發者很容易顯示圖片, 並讓我們使用不同的修飾器來產生各種的圖片效果。如果你是獨立開發者,這些新導入的 SF Symbols 會節省你尋找第三方圖示的時間。
在本章所準備的範例檔中,有完整的專案可以下載: