[Day 21] 里程定位與地圖顯示(七)- TapGesture & Sheet
接續昨天的進度,現在地圖上的圖標已經能按照資料集的經緯度精確標出位置,並在圖標上方顯示道路名稱與里程數。然而,僅有這些資訊是不夠的,我們需要提供一個更豐富的互動方式,讓使用者能深入了解每個地點的詳情。 一個常見的解決方案是,讓使用者點擊圖標後,從螢幕下方彈出一個包含詳細資訊的 sheet。這種做法不僅能呈現更多內容,還能確保使用者無需離開當前頁面,從而避免割裂感,提供流暢的使用體驗。 選擇最適合的 Sheet 呈現方式 要使用 SwiftUI 彈出 sheet,蘋果官方提供了幾種不同的方法,其中最常見的兩種是: sheet(isPresented:onDismiss:content:) 這個方式是綁定一個 Bool 參數,來判斷是否需要 present sheet。 sheet(item:onDismiss:content:) 這裡的 item 綁定的是一個可選型別 (Optional) 的物件,透過當這個參數傳入的物件為是否為有值來決定彈出 sheet 與否。這應該是會比較適合我們的實作方式,因為我們的 sheet 內容是要與圖標物件綁定的。 考慮到我們的 sheet 需要顯示特定圖標的詳細資訊,第二種方法顯然更適合我們的實作場景。 步驟一:綁定狀態與觸發事件 首先,我們在 MapView 中宣告一個 @State 變數 selectedPin,它的型別是 MarkerPin?(可選的 MarkerPin)。因為使用者一開始尚未選擇任何圖標,所以它的初始值為 nil。 @State private var selectedPin: MarkerPin? = nil 接著,我們在 MapView 的最外層容器 ZStack 上附加 .sheet 修飾符,並將它的 item 參數綁定到 $selectedPin。 var body: some View { ZStack(alignment: .top) { Map(position: $cameraPosition) { // .. } } .sheet(item: $selectedPin) { pin in // 在這個閉包中,`pin` 就是使用者所點擊的那個 MarkerPin 物件 // 我們將在這裡建構 sheet 的內容 } } 現在,我們只需要在使用者點擊圖標時,將該圖標的物件指派給 selectedPin 即可。我們回到 Annotation 的程式碼,為其加上 .onTapGesture 事件: ...