#12 Music player實現播放暫停、上下首、音量調整與圓形進度條功能

始終對音樂播放器的介面設計很有興趣,因為是結合資訊、互動與娛樂效果的互動。

這次特別嘗試將音樂播放進度以圓形進度條形式呈現,先忽略手動調整播放進度的操作,待之後與隨機和重複播放功能一起實踐。

介面佈局

將除了專輯封面與圓形進度條外的元件佈局在Storyboard上。

利用 AVPlayer 播放 App 裡的音樂

音樂檔案與歌名的陣列

將音樂檔案放入專案並以陣列方式儲存,以後面切換時調用

let songTitle = ["The Kids Are Coming","Dance Monkey","Colourblind","Johnny Run Away","Jimmy","Never Seen the Rain"]let songName = ["01.The Kids Are Coming","02.Dance Monkey","03.Colourblind","04.Johnny Run Away","05.Jimmy","06.Never Seen the Rain"]

AVPlayer

let player = AVPlayer()
var playerItem: AVPlayerItem?
var fileUrl = Bundle.main.url(forResource: nil, withExtension: "mp3")

播放音樂

func playSong(index: Int) {
fileUrl = Bundle.main.url(forResource: songName[index], withExtension: "mp3")!
playerItem = AVPlayerItem(url: fileUrl!)
player.replaceCurrentItem(with: playerItem)
player.play()
setImage(imageName: "pause.circle")
songLable.text = songTitle[songIndex]
}

Play / Pause Button

@IBAction func playMusic(_ sender: UIButton) {

if player.timeControlStatus == .paused {
setImage(imageName: "pause.circle")
player.play()
}else {
setImage(imageName: "play.circle")
player.pause()
}
}

Previous Button

@IBAction func previousSong(_ sender: UIButton) {
if songIndex == 0 {
songIndex = songName.count - 1
playSong(index: songIndex)
songTotalLength()
}else {
songIndex -= 1
playSong(index: songIndex)
songTotalLength()

}
}

音樂播放時間

音樂長度

func songTotalLength() {        //讀取歌曲的音樂長度  
let duration = playerItem!.asset.duration
let seconds = CMTimeGetSeconds(duration)
//將播放進度賦值給totalTimeLabel
totalTimeLabel.text = formateConversion(time: seconds)

//將時間長度賦值給totoalTime
totoalTime = seconds
}

播放進度條圖形的函式

總長度即為360度,不需定義。但須計算當前播放進度跟音樂長度的比例取得圓環角度。

func songProgressBar(time: CGFloat) -> UIView {
let startAngle = CGFloat.pi / 2 * 3

//當前進度除以音樂長度取得角度
let angle:CGFloat = 360 * time / totoalTime
let endAngle = startAngle + angle.degree

let songCurrenPath = UIBezierPath()
songCurrenPath.addArc(withCenter: CGPoint(x: 0, y: 0), radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
songCurrentShape.path = songCurrenPath.cgPath
songCurrentShape.strokeColor = UIColor.orange.cgColor
songCurrentShape.lineWidth = 4
songCurrentShape.lineCap = .round
songCurrentShape.fillColor = UIColor.clear.cgColor
barView.layer.addSublayer(songCurrentShape)

return barView
}

觀察音樂播放進度

func songCurrentTime() {

let timeScale = CMTimeScale(NSEC_PER_SEC)
let time = CMTime(seconds: 0.5, preferredTimescale: timeScale)
player.addPeriodicTimeObserver(forInterval: time, queue: .main, using: { (time) in

if self.player.currentItem?.status == .readyToPlay {

let currentTime = CMTimeGetSeconds(self.player.currentTime())

//將播放進度賦值給currentTimeLabel
self.currentTimeLabel.text = self.formateConversion(time: currentTime)

//將播放進度賦值給圖形函式
self.songProgressBar(time: currentTime)

}
})
}

成果

--

--