上一節用List列出傑森解碼器傳回的「特有種列表」,接下來,我們希望點選鳥種時,展示該鳥種的圖片及叫聲,這時候就需要用第3課學過的3-3d iTunes 搜尋與播放試聽(NavigationStack) 與3-3c 播放網路影音(AVKit) 。
先仿照第3課範例程式3-3d,將上一節的List前後插入NavigationStack及NavigationLink:
NavigationStack {
List(特有種清單) { 鳥種 in
NavigationLink(destination: 圖片與聲音(鳥種)) {
Label(鳥種.中文名 + 鳥種.英文名, systemImage: "photo")
.font(.title2)
.lineLimit(1)
}
}
.navigationTitle("台灣特有種鳥類")
}
這段程式碼結構如下,內層由①NavigationLink將「Label()」與「圖片與聲音()」兩個視圖連結在一起,外層由②List()將「特有種清單」陣列的元素一一傳遞給Label(),形成列表,最外面再包一層③NavigationView (改為NavigationStack),以控制整個螢幕畫面。
剩下的工作,就只需寫個展示「圖片與聲音」的視圖,這個工作又分成兩部分:展示圖片以及播放聲音。
圖片部分比較簡單,直接拿前面第6課範例3-6b來修改即可:
AsyncImage(url: URL(string: 鳥種.圖片網址)) { 狀態 in
if let 圖片 = 狀態.image {
VStack(alignment: .leading) {
圖片
.resizable()
.scaledToFit()
Text(鳥種.中文名 + 鳥種.英文名)
Text("攝影者:\\(鳥種.攝影者)")
Text("錄音者:\\(鳥種.錄音者)")
}
} else if 狀態.error != nil {
Image(systemName: "xmark.icloud.fill")
.scaleEffect(3)
.foregroundColor(.red)
} else {
ProgressView()
}
}
差別只有在圖片下方增加了三行文字,當作圖說,以符合CC版權要求。
聲音部分稍有波折,主要參照第3課播放iTune歌曲的方法,不過這次不需要播放器外觀(而是在背景播放),所以可略過 VideoPlayer 物件,只需用 AVPlayer,兩者差異如下表。
物件 | AVPlayer | VideoPlayer |
---|---|---|
所屬物件庫 | AVFoundation | AVKit |
用途 | [內部控制]設定影音檔來源、透過作業系統控制播放參數(音量、播放、暫停等) | [外觀]顯示播放器外觀,提供使用者控制介面(音量、播放、暫停等) |
要在背景播放聲音檔(如網路的MP3),最基本只要兩行程式碼就能搞定:
let 播放器 = AVPlayer(url: myURL)
播放器.play()
就可播放 myURL 網址的mp3或其他聲音檔案,如果網址不對或聲音格式未支援,並不會拋出錯誤,只是聽不到任何聲音。
我們可以在視圖初始化函式 init() 中,帶入「鳥類」為參數,以指定「錄音網址」給播放器,然後利用 .onAppear 修飾語來播放聲音,相對的,在 .onDisappear 脫離視圖時暫停播放,程式碼如下: