SwiftUI 框架

iOS 18 新API:使用 Navigation Transition 創建 Hero 動畫式過場

iOS 18 新API:使用 Navigation Transition 創建 Hero 動畫式過場
iOS 18 新API:使用 Navigation Transition 創建 Hero 動畫式過場
In: SwiftUI 框架

Apple 的工程師可能早已認識到,許多 iOS 開發者都希望能夠重現 App Store 應用程式中的優雅 Hero 動畫。由於從頭實現這種動畫通常需要耗費大量時間與精力,Apple 在 iOS 18 SDK 中納入了這項功能。

透過這次更新,你現在只需少量的程式碼就能在自己的應用程式中實現類似的動畫過渡效果。這項重大改進讓開發者能夠創造出更具視覺吸引力且流暢的過渡效果,進而提升應用程式的整體使用者體驗。

在本教程中,我們將探討如何利用新的 NavigationTransition 協定(protocol)以及 matchedTransitionSource 修飾符來在視圖過渡期間創建 Hero 動畫。

簡單的示範應用程式

讓我們透過一個示範應用程式來探索這些新 API。我們將從一個顯示咖啡廳列表的標準捲動視圖開始。我們的目標是實現一個功能,讓使用者點擊咖啡廳後,能夠進入顯示完整圖片的新畫面,並伴隨 Hero 動畫效果。

使用 Navigation Transition 協定

要顯示完整圖片並使用 Hero 動畫來進行視圖過場,可以按照以下步驟進行:

  1. 將捲動視圖嵌入到導航堆疊(navigation stack)中。
  2. 使用 NavigationLink 來啟用卡片視圖的點擊功能。
  3. 宣告一個帶有 @Namespace 的命名空間,以支援 Hero 動畫。
  4. matchedTransitionSource 修飾符附加到摘要模式的卡片視圖上。
  5. navigationTransition 修飾符附加到完整內容模式的卡片視圖上。

完成這些步驟後,SwiftUI 將自動產生一個流暢的 Hero 動畫,當點擊選中的咖啡廳項目時,會將其擴展為全螢幕圖片。

為視圖過場創建 Hero 動畫

現在我們將修改專案以支援導航功能。首先,將捲動視圖嵌入到導航堆疊中,如下所示:

NavigationStack {
	ScrollView {
	
		// Existing code
		
	}
}

接下來,建立一個用於顯示完整圖片的詳細視圖,如下所示。這個視圖會接受一個咖啡廳物件作為輸入,並在全螢幕視圖中顯示其圖片。

struct DetailView: View {
    var cafe: Cafe
    @Environment(\.dismiss) var dismiss
    
    var body: some View {
        Image(cafe.image)
            .resizable()
            .scaledToFill()
            .frame(minWidth: 0, maxWidth: .infinity)
            .clipped()
            .overlay(alignment: .topTrailing) {
                Button {
                    dismiss()
                } label: {
                    Image(systemName: "xmark.circle.fill")
                        .font(.system(size: 30))
                        .foregroundStyle(Color.white)
                        .opacity(0.7)
                        .padding()
                        .padding(.top, 30)
                }
            }
            .ignoresSafeArea()
    }
}

為了啟用與咖啡廳圖片的互動,我們可以使用 NavigationLink 來管理導航功能。當被點擊時,應用程式會顯示詳細視圖,並以全螢幕方式呈現圖片。

ForEach(sampleCafes) { cafe in
    
    NavigationLink {
        DetailView(cafe: cafe)
        
    } label: {
        Image(cafe.image)
            .resizable()
            .scaledToFill()
            .frame(minWidth: 0, maxWidth: .infinity)
            .frame(height: 400)
            .clipShape(RoundedRectangle(cornerRadius: 20))
    }
    .padding()
}

在預覽模式下,你可以在詳細視圖與列表視圖之間進行導航。此時,過渡效果使用的是導航堆疊的預設動畫,並未加入任何自訂效果。

現在來到有趣的部分了。我們將使用新的 NavigationTransition 協定來創建 Hero 動畫。第一步是為動畫定義一個命名空間。在 ContentView 中,宣告以下命名空間變數:

@Namespace var namespace

接著,將 matchedTransitionSource 修飾符應用到來源視圖,也就是列表中的圖片視圖。然後,在詳細視圖上使用 navigationTransition 修飾符。按照下面的程式碼更新你的應用程式:

NavigationLink {
    DetailView(cafe: cafe)
        .navigationTransition(.zoom(sourceID: cafe.id, in: namespace))
        .toolbarVisibility(.hidden, for: .navigationBar)
    
} label: {
    Image(cafe.image)
        .resizable()
        .scaledToFill()
        .frame(minWidth: 0, maxWidth: .infinity)
        .frame(height: 400)
        .clipShape(RoundedRectangle(cornerRadius: 20))
        .matchedTransitionSource(id: cafe.id, in: namespace)
}

為了增強視覺體驗,我還加入了 toolbarVisibility 修飾符來隱藏導航列。這樣可以移除返回按鈕,呈現一個更具沉浸感的全螢幕咖啡廳圖片展示。

在預覽模式下,測試應用程式,點擊咖啡廳圖片時,將會顯示帶有 Hero 動畫的全螢幕圖片。要返回列表,可以點擊「X」按鈕或直接向下拖動圖片。應用程式會將圖片以動畫方式還原到列表中的原始位置,提供一個流暢且直觀的使用者體驗。

總結

新的 NavigationTransition 協定讓開發者能夠輕鬆地創建視圖過渡的 Hero 動畫,只需幾行的程式碼便能提供更豐富的使用者體驗。建議你探索這個新功能,來提升應用程式的互動性和使用者滿意度。

需要注意的是,這個 API 僅適用於 iOS 18 及之後的版本。如果你的應用程式需要支援舊版 iOS,你將需要自行實作這個動畫。我們的《精通 SwiftUI》一書提供了如何實現這類效果的詳細指導。

作者
Simon Ng
軟體工程師,AppCoda 創辦人。著有《iOS 18 App 程式設計實戰心法》、《iOS 18 App程式設計進階攻略》以及《精通SwiftUI》。曾任職於HSBC, FedEx等跨國企業,專責軟體開發、系統設計。2012年創立AppCoda技術部落格,定期發表iOS程式教學文章。現時專注發展AppCoda業務,致力於iOS程式教學、產品設計及開發。你可以到推特與我聯絡。
評論
更多來自 AppCoda 中文版
如何在 SwiftUI App 中開發 Live Activities
SwiftUI 框架

如何在 SwiftUI App 中開發 Live Activities

Live Activities 首次於 iOS 16 推出,是 Apple 最令人興奮的更新之一,能讓 App 與使用者在即時互動上更有連結。它不再需要使用者不斷打開 App,Live Activities 可以讓資訊直接顯示在鎖定畫面和 Dynamic Island 上。
使用 Tool Calling 強化 Foundation Models 功能
AI

使用 Tool Calling 強化 Foundation Models 功能

在前幾篇教學中,我們介紹了 Foundation Models 在 iOS 26 中的運作方式,以及如何使用這個全新框架打造具備 AI 功能的應用。我們也介紹了 @Generable 巨集,它能輕鬆地將模型回應轉換為結構化的 Swift 類型。 現在,在這個 Foundation
活用 Foundation Models 的 @Generable 與 @Guide 製作測驗 App
AI

活用 Foundation Models 的 @Generable 與 @Guide 製作測驗 App

在前一篇教學中,我們介紹了 Foundation Models 框架,並示範了如何用它來進行基本的內容生成。那個過程相當簡單——你提供一個提示詞(prompt),等幾秒鐘,就能獲得自然語言的回應。在我們的範例中,我們建立了一個簡單的問答 App,讓使用者可以提問,App 則直接顯示生成的文字。 但如果回應變得更複雜——你需要把非結構化文字轉換為結構化的物件呢? 舉例來說,
很好! 你已成功註冊。
歡迎回來! 你已成功登入。
你已成功訂閱 AppCoda 中文版 電子報。
你的連結已失效。
成功! 請檢查你的電子郵件以獲取用於登入的連結。
好! 你的付費資料已更新。
你的付費方式並未更新。