顯示美麗圖片的 SwiftUI image

顯示圖片

生成 Image,( ) 裡傳入 Assets.xcassets 裡圖片的名字。

struct ContentView: View {
var body: some View {
Image("peter")
}
}

圖片顯示的預設大小將是當初圖檔的大小。如下圖所示,1x 格子的圖片大小為 1422 * 892 pixels,因此 App 畫面上圖片的大小將為 1422 * 892 points。

將 preview 切換到 Selectable mode,可發現圖片明顯超出 iPhone 的螢幕範圍。

自動將 asset 的圖片和顏色變成 ImageResource 和 ColorResource 的型別屬性

從 Xcode 15 開始,我們可以更方便地從程式生成圖片,Xcode 會自動將 asset 的圖片變成方便輸入的型別屬性。

struct ContentView: View {
var body: some View {
Image(.peter)
}
}

縮放圖片的 resizable

若想改變圖片的大小,則須呼叫縮放圖片的 resizable。

var body: some View {
Image(.peter)
.resizable()
}

呼叫 resizable() 後,圖片將縮放到目前可用空間的大小。以剛剛的程式為例,目前可用空間為螢幕的大小,不包含上方和下方的圓角區塊。此時圖片其實是有點變形的,待會我們將看到如何維持圖片比例。

搭配 tile 實現圖片平鋪排列

當我們呼叫 resizable 時,它預設會以延伸的方式縮放圖片,但我們也可以另外指定它維持原圖大小,一個個排列填滿整個空間。

如以下程式所示,參數 resizingMode 可控制圖片縮放的方式,傳入 .tile 將生成一個個彼得潘的圖片填滿畫面。(另一個可傳入的內容為 .stretch,代表預設的延伸縮放 )

Image(.peterLogo)
.resizable(resizingMode: .tile)

指定大小的 frame

利用 function frame(width:height:alignment:) 可指定元件的寬高。值得注意的,我們必須先呼叫 function resizable(),讓圖片變成可以縮放大小,然後再呼叫 frame(width:height:alignment:)。

struct ContentView: View {
var body: some View {
Image(.peter)
.resizable()
.frame(width: 300, height: 300)
}
}

沒有呼叫 resizable 會怎樣呢 ? 如下圖所示,圖片將不為所動地維持原本的大小。

var body: some View {
Image(.peter)
.frame(width: 300, height: 300)
}

縮放時維持圖片比例

當我們利用 resizable 修改大小後,圖片將變形縮放。若想要圖片不變形,可考慮使用 scaledToFit 或 scaledToFill。

  • 讓圖片維持比例但左右或上下留白的 scaledToFit
struct ContentView: View {
var body: some View {
Image(.peter)
.resizable()
.scaledToFit()
}
}

如下圖所示,圖片變成螢幕裡它可以維持比例的最大尺寸。

  • 維持比例並指定寬高
struct ContentView: View {
var body: some View {
Image(.peter)
.resizable()
.scaledToFit()
.frame(width: 300, height: 300)
}
}

將 preview 切換到 Selectable mode,可發現圖片將上下或左右留白。

若想多打一點程式,也可以用 aspectRatio(contentMode: .fit) 取代 scaledToFit(),它們有一樣的效果。

  • 讓圖片維持比例並佔滿空間的 scaledToFill
struct ContentView: View {
var body: some View {
Image(.peter)
.resizable()
.scaledToFill()
}
}

將 preview 切換到 Selectable mode,可發現圖片維持比例並佔滿螢幕,因此有部分的區塊超出畫面。

  • 維持比例並佔滿指定的寬高
struct ContentView: View {
var body: some View {
Image(.peter)
.resizable()
.scaledToFill()
.frame(width: 300, height: 300)
}
}

將 preview 切換到 Selectable mode,可發現圖片會有左右或上下的部分區塊超出 frame 設定的框框

若想切除超出的區塊,請再加上 clipped。

struct ContentView: View {
var body: some View {
Image(.peter)
.resizable()
.scaledToFill()
.frame(width: 300, height: 300)
.clipped()
}
}

在調整圖片如何縮放時,要記得別在 frame 設定大小後才調整。如下圖所示,我們在 frame 設定大小後再呼叫 scaleToFit,此時它將成為無效的程式,起不了任何作用,圖片依然變形。

struct ContentView: View {
var body: some View {
Image(.peter)
.resizable()
.frame(width: 300, height: 100)
.scaledToFit()
}
}

利用 scaledToFit 顯示完整圖片

當我們想顯示完整的圖片時,滿常搭配 scaledToFit,相關說明可參考以下連結。

圖片的圓角和邊框

讓 scaledToFill 圖片等於螢幕寬度的方法

搭配 alignment 設定對齊的位置

當我們以 frame 指定大小時,圖片內容預設會在指定大小的框框裡置中顯示。

不過我們也可以透過 alignment 調整,比方設定 .top 將讓框框對齊圖片的上邊界。

Image(.peter)
.frame(width: 100, height: 100, alignment: .top)
Image("peter")
.frame(width: 100, height: 100, alignment: .top)
.clipped()

讓圖片維持比例佔滿指定的寬高,並且置頂。

Image(.peter)
.resizable()
.scaledToFill()
.frame(width: 300, height: 100, alignment: .top)
.clipped()

沒有設定 alignment 時,預設會是置中。

Image(.peter)
.resizable()
.scaledToFill()
.frame(width: 300, height: 100)
.clipped()

生動有趣的圖片效果 modifier

--

--

彼得潘的 iOS App Neverland
彼得潘的 Swift iOS App 開發問題解答集

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com