#10 用 page control, button & gesture 更換內容

Fraser Chang
彼得潘的 Swift iOS App 開發教室
9 min readJul 29, 2023

--

使用 outlet, action 控制頁面 Button, Gesture, Page Control 元件,實現更新頁面顯示內容。

AVFoundation
使用 AVPlayer 製作音樂播放器
連結本地音樂資源內容,點擊按鈕開始播放、暫停、上一首、下一首

元件配置

新建並修改 ViewController 類別後按下要連線的元件,使用 Assistant 呼叫出與此元件相關的 Controller 類別文件。

-1. 左圖點按的方式
-2. cmd + shift + A 呼叫出 Quick Actions 輸入 ass 啟用

使用 Segue 將元件連線至自訂類別文件內,建立 function 控制畫面內容

讀取屬性、變更內容的元件以 Outlet 方式建立至文件內(名詞命名)
要執行互動元件的按鈕,以 Action 連線(動詞命名)
連線拉至上方區域時,預設出現 Outlet
拉至下方區域則出現 Action

因為這邊的 Button 元件都是要被點選互動的,因此都要建立 Action

播放音樂、下一首與上一首的 Botton
PageControl、下一頁與上一頁的 Botton

要讀取元件的屬性或要變更其內容的元件則建立 Outlet

UIImageView、UILabel、UITextView
PageControl:在切換頁面內容時會需要讀取與變更小白點位置

建立電影介紹與原聲帶內容

let movieImageArray = ["HurryPorter","YourName","SweetHome"]
let movieTitleArray = ["Harry Prtter","你的名字","SweetHome"]
let movieSubTitleArray = ["The Deathly Hallows – Part 2","君の名は","스위트홈"]
let movieContentArray = ["在終極篇的第二部,正邪一戰將會全面爆發。危機升級至前所未見的凶險,沒有一個人能置身事外。但是,只有哈利波特一人會需要獨自與佛地魔展開終極一戰。到底誰勝誰負呢?","故事敘述居住在東京的少年立花瀧與糸守町出身的少女宮水三葉,偶然發現彼此的意識會互換至對方身上後,所延伸的連串奇異際遇。","講述主角家人離世後獨自搬到「綠之家」居住。在自殺的那天,發生一連串恐怖事件,在公寓被怪物襲擊後,跟鄰居並肩作戰對抗怪物。"]
let musicArray = [["Statues","Harry's Sacrifice","Lily's Theme"],["なんでもないや","夢灯籠","憧れカフェ"],["Sweet Home","Dark Sun","Monster Slayers"]]

PageControl Action function 設定

    @IBAction func PageControl(_ sender: Any) {
index = pageControl.currentPage //使用時點選並改變元件後,帶入index
updateUI() //呼叫 function 改變畫面內容
}

建立上一頁、下一頁控制 Button Function

    @IBAction func nextPage(_ sender: Any) {
index = ( index + 1 + movieTitleArray.count ) % movieTitleArray.count
updateUI()
} //按下 Button ,變更 index 後呼叫 updateUI

變更頁面上顯示的訊息

//使用元件變更 index 後,畫面的訊息都要同步跟著改變
//將更新的內容變更至以 Outlet 建立的屬性元件內
func updateUI() {
movieImageView.image = UIImage(named: movieImageArray[index])
movieTitle.text = movieTitleArray[index]
movieSubTitle.text = movieSubTitleArray[index]
movieContent.text = movieContentArray[index]
pageControl.currentPage = index
//因為頁面內容變更了,小白點的位置也要跟著換位置才行
currentAudio = 0
//切換頁面後,音樂 Array 內容也要跟著改變
if audioPlayer.timeControlStatus == .playing { audioStop() }
//音樂停止播放
let musicItem = AVPlayerItem(url: Bundle.main.url(forResource: musicArray[index].first, withExtension: "mp3")!)
audioPlayer.replaceCurrentItem(with: musicItem)
//更改播放器內的音樂檔案
}

建立音樂播放器前,要引入合適的 SDK

import AVFoundation

把檔案拉入專案視窗內,勾選 Copy items if needed(複製到專案資料夾內使用,避免檔案遺失時連結就失效了)

參考上面方式獲取本地的音樂連結位置

let musicItem = AVPlayerItem(url: Bundle.main.url(forResource: musicList[index], withExtension: "mp3")!)
//Bundle.main 專案的捆包內
//forResource 直接輸入檔案名稱:"夢灯籠"
//withExtension 檔案副檔名
audioPlayer.replaceCurrentItem(with: musicItem)
//把播放器的項目改成我們要的音樂檔

實現音樂功能按下開始,按下暫停

if audioPlayer.timeControlStatus == .paused {
//檢查按下按鈕時,播放器目前是否停止狀態
playIcon.setImage(UIImage(systemName: "pause.fill"), for: .normal)
//停止狀態顯示停止圖示
if audioPlayer.currentItem == nil {
//播放器內如果當前沒檔案就放入該電影 Array 內的第一首
let musicItem = AVPlayerItem(url: Bundle.main.url(forResource: musicList.first, withExtension: "mp3")!)
audioPlayer.replaceCurrentItem(with: musicItem)
}
audioPlayer.play()
//播放音樂
} else {
playIcon.setImage(UIImage(systemName: "play.fill"), for: .normal)
audioPlayer.pause()
//變更圖示為播放圖示並暫停
}

跳至上一首/下一首

@IBAction func nextMusic(_ sender: Any) {
let musicList = musicArray[index]
let musicNumber = audioChang( index, current: currentAudio, changed: 1)
//呼叫 audioChang 變更歌曲索引值
let musicItem = AVPlayerItem(url: Bundle.main.url(forResource: musicList[musicNumber], withExtension: "mp3")!)
//更改 AVPlayerItem 的音樂
audioPlayer.replaceCurrentItem(with: musicItem)
currentAudio = musicNumber
}
Notes:  許多的進階元件功能,隨機播放、循環播放、播放進度控制與顯示日後研究更新

GitHub:

--

--