Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> swift版QQ音樂播放器(二)

swift版QQ音樂播放器(二)

編輯:關於Android編程

一 完善部分的QQ音樂效果圖

這裡寫圖片描述

二 需要完善點

1 歌曲的切換和暫停播放

2 歌曲當前播放時間和歌曲總時間的更新

3 進度條的處理

4 歌手頭像處理

5 頭像動畫效果

6 歌詞的進度顯示

8 完善細節

三 添加歌曲展示頁面中的動畫效果

1 代碼書寫位置 : 由於展示歌詞的控制器的UITableViewController,那麼我們可以使用代理方法.當用戶拖動tableView的時候,會調用一個方法,在該方法中實現動畫效果

2 思路 : 通過拿到第一個cell和最後一個cell來計算中間cell的索引值,然後遍歷所有的索引,取出cell在分別計算各個cell的x值.就可以達到目的.

3 直接奉上代碼 :

    //** 實現一種動畫效果 */
    override func scrollViewDidScroll(scrollView: UIScrollView) {
        //獲取指定的cell
        guard let indexRows = tableView.indexPathsForVisibleRows else {
            return
        }
        //** 獲取中間的cell */
        let firstCell = indexRows.first?.row ?? 0
        let lastCell = indexRows.last?.row ?? 0

        //** 計算中間的cell */
        let middleCell = Int(Float(firstCell + lastCell) * 0.5)
        //** 遍歷指定的所有的cell */
        for indexRow in indexRows {
            //取出cell
            let cell = tableView.cellForRowAtIndexPath(indexRow)
            cell?.x = CGFloat(abs(indexRow.row - middleCell) * 40)
            print(indexRow.row - middleCell)
        }
    }

四 處理音樂切換和暫停播放

1 通過在storyboard中自動布局,達到下面圖中的效果(這裡我就不一 一細說了,都是基本)

這裡寫圖片描述

2 通過從storyboard拖線的方式我們可以拿到需要設置的東西

—-> 2.1 注意擺放位置 : 這裡我們按照經常需要改變的屬性和只改變一次屬性的模式來擺放代碼.

3 代碼部分 :

—-> 3.1 只需要改變一次的屬性(裡面包含了上一篇中的部分屬性)
    //** 歌曲名稱 */
    @IBOutlet weak var nameLabel: UILabel!
    //** 歌手名稱 */
    @IBOutlet weak var singerLabel: UILabel!
    //** 總音樂時間 */
    @IBOutlet weak var totalLabel: UILabel!
    //** 歌手背景圖片 */
    @IBOutlet weak var singerImageView: UIImageView!
    //** 能讓現實歌詞的view拖動的scrollView */
    @IBOutlet weak var lrcSImageView: UIScrollView!
    //** 歌手專輯圖片 */
    @IBOutlet weak var backImageView: UIImageView!
    //** 暫停或者播放 */
    @IBOutlet weak var playOrPause: UIButton!
—-> 3.2 經常需要改變的屬性(裡面包含了上一篇中的部分屬性)
    //** 當前時間 */
    @IBOutlet weak var currentLabel: UILabel!
    //** 顯示歌詞的label */
    @IBOutlet weak var lrcLabel: UILabel!
    //** 滑塊 */
    @IBOutlet weak var silderProgress: UISlider!

4 封裝工具類(封裝調用思想: 三層調用)

—-> 4.1 工具類一 : 對單首音樂的播放狀態工具類(往裡面添加繼續播放;暫停播放的方法)
———-> 4.1.1 該部分代碼 :
    //** 繼續播放音樂 */
    func playMusic() {
        player?.play()
    }

    //** 暫停播放 */
    func pauseMusic() {
        player?.pause()
    }
—-> 4.2 工具類二 : 在負責音樂的業務邏輯工具類(獲取最新音樂數據;重新播放音樂;暫停播放音樂;上一首和下一首)
———-> 4.2.1 記錄播放歌曲的索引
    //** 創建音樂播放列表 (XFJQQMusicListItem: 音樂列表的模型)*/
    var musicList : [XFJQQMusicListItem]?
    //** 提供一個記錄歌曲的索引 */
    var index = 0 {
        didSet {
            //判斷
            if index < 0 {
                index = (musicList?.count ?? 0) - 1
            }
            if index > ((musicList?.count ?? 0) - 1){
                index = 0
            }
        }
    }
———-> 4.2.2 創建另外一個模型

這裡寫圖片描述

———-> 4.2.3 問題 : 怎麼才能當前創建的模型具有第一個模型中的屬性呢?
———-> 4.2.4 解決 : 才用擁有的方法(讓第一個模型作為第二個模型中的屬性)
———-> 4.2.5 新創建的模型需要考慮到的屬性 : 當前播放時間;歌曲總時間;播放狀態
———-> 4.2.6 設計屬性采用的方法 : 對當前時間和總歌曲時間提供get方法
———-> 4.2.7 具體代碼如下 :

class XFJQQMusicNewMessageModel: NSObject {
//* 讓該模型擁有顯示歌單的模型 /
var QQMusicItem : XFJQQMusicListItem?
//* 當前播放的時間 /
var costTime : NSTimeInterval = 0
//* 總播放的時間 /
var totalTime : NSTimeInterval = 0

//** 提供當前時間和總時間的get方法 */
var costFormatTime : String {
    get{
        return XFJQQTimeTool.getTime(costTime)
    }
}

//** 提供總時間的get方法 */
var totalFormatTime : String {
    get{
        return XFJQQTimeTool.getTime(totalTime)
    }
}
//** 播放的狀態 */
var isPlaying : Bool = false

}

—-> 4.3 在回到負責音樂業務類的工具類中.提供一個方法,負責返回最新的數據
    //** 設置一個方法用來提供最新的數據 */
    func getQQMusicNewMessage() ->XFJQQMusicNewMessageModel {
        //** 給暫時歌詞中的模型屬性賦值,保持最新的數據 */
        QQMusicMessageModel.QQMusicItem = musicList![index]
        //** 當前播放的進度 */
        QQMusicMessageModel.costTime = tool.player?.currentTime ?? 0
        //** 歌曲的總時長 */
        QQMusicMessageModel.totalTime = tool.player?.duration ?? 0
        //** 播放狀態 */
        QQMusicMessageModel.isPlaying = tool.player?.playing ?? false
        //** 返回最新的數據模型 */
        return QQMusicMessageModel
    }

—-> 4.4 在該業務中提供一個方法對音樂的處理(判斷音樂列表;記錄當前播放音樂的索引)

    //設置一個方法對音樂的處理
    func playMusic(musicM : XFJQQMusicListItem) {
        //取出模型中的音樂文件名
        let fileName = musicM.filename ?? ""
        //傳入音樂文件名播放音樂
        tool.playMusic(fileName)
        //** 判斷如果列表中沒有音樂就直接返回 */
        if musicList == nil {
            return
        }

        //** 並且記錄當前的音樂索引 */
        index = (musicList?.indexOf(musicM))!
    }

—-> 4.5 在該類中在封裝一層方法(方法內部分別調用在對單首音樂處理的方法中的繼續播放和暫停播放的方法;上一首;下一首的方法)

—-> 4.5.1 重新播放和暫停播放代碼 :

    //** 重新播放 */
    func playCurrentMusic() ->() {
        tool.playMusic()
    }
    //** 暫停播放 */
    func pauseCurrentMusic() {
        tool.pauseMusic()
    }

—-> 4.5.2 上一首和下一首代碼 :

    //** 上一首 */
    func preMusic() {
        //索引遞減
        index -= 1

        //判斷
        if let muiscM = musicList {
            //取出模型
            let music = muiscM[index]
            //播放音樂
            playMusic(music)
        }   
    }
    //** 下一首 */
    func nextMusic() {
        //索引增加
        index += 1
        //判斷
        if let musicM = musicList {
            //取出模型
            let music = musicM[index]
            //播放
            playMusic(music)
        }
    }
—-> 4.6 工具類三 : 對音樂播放的時間和音樂總時間的處理(轉化為具體的分鐘和秒鐘)
—-> 4.6.1 具體代碼詳解 :
class XFJQQTimeTool: NSObject {    
    class func getTime(time : NSTimeInterval) ->String {
        let min = Int(time / 60)
        let sec = Int(time) % 60

        //** 轉成字符串 */
        let resultStr = String(format: "%02d:%02d", min,sec)
        //** 返回結果 */
        return resultStr
    }
}
—-> 4.7 提供兩個方法(分別用來作為該內部調用的 : 對經常執行的和不經常的方法分開存放 )—> 同樣采用了分層存放的方法
—-> 4.7.1 在展示歌詞的類擴展中設置兩個方法(詳見代碼: 該部分上篇博客已經講解了)
    //** 設置一次 */
    private func setUpOnce() {
        setUpViewOnce()
        setUpSilder()
    }
    //** 設置多次 */
    private func setUpTimes() {
        setUpViewFrame()
        setUpForeImage()
    }
—-> 4.8 根據從storyboard中得到的數據,采用最新創建的模型中的數據來對其賦值(只需要設置一次 : 詳見代碼)
    //** 只需要設置一次的數據 */
    private func setUpDataTime() ->() {
        let musicMessageModel = XFJQQMusicOperationTool.shareInstance.getQQMusicNewMessage()
        //** 歌曲名稱 */
        nameLabel.text = musicMessageModel.QQMusicItem?.name
        //** 歌手背景圖片 */
        singerImageView.image = UIImage(named: (musicMessageModel.QQMusicItem?.icon ?? ""))
        //** 歌手專輯圖片 */
        backImageView.image = UIImage(named: (musicMessageModel.QQMusicItem?.icon)!)
        //** 歌手名稱 */
        singerLabel.text = musicMessageModel.QQMusicItem?.singer
        //** 歌曲總時間 */
        totalLabel.text = "\(musicMessageModel.totalFormatTime)"
    }
—-> 4.9 根據從storyboard中得到的數據,采用最新創建的模型中的數據來對其賦值(只需要設置多次 : 詳見代碼)
    //** 設置多次的數據 */
    func setUpDatasTimes() {
        let musicMessageModel = XFJQQMusicOperationTool.shareInstance.getQQMusicNewMessage()
        //** 當前播放時間 */
        currentLabel.text = "\(musicMessageModel.costFormatTime)"
        //** 進度條 */
        silderProgress.value = Float(musicMessageModel.costTime / musicMessageModel.totalTime)

        //** 播放狀態 */
        playOrPause.selected = musicMessageModel.isPlaying
    }
—-> 4.10 由於用戶需要點擊具體的按鈕來切換相應的業務邏輯,那麼我們也采取拖線的方式來達到效果
—-> 4.11 播放和暫停(用單例直接調用工具類中設置的方法)
    //** 播放和暫停 */
    @IBAction func playAndPause(button : UIButton)
    {
        //判斷
        button.selected = !button.selected
        if button.selected {
            XFJQQMusicOperationTool.shareInstance.playCurrentMusic()
        }else{
            XFJQQMusicOperationTool.shareInstance.pauseCurrentMusic()
        }
    }
—-> 4.11 歌曲的切換(直接調用工具類中封裝的方法和對屬性進行設置的方法)
    //** 上一首 */
    @IBAction func preButton()
    {
        let operationTool = XFJQQMusicOperationTool.shareInstance

        //調用播放上一首的方法
        operationTool.preMusic()
        setUpDataTime()
    }

    //** 下一首 */
    @IBAction func nextButton()
    {
        let operationTool = XFJQQMusicOperationTool.shareInstance
        operationTool.nextMusic()
        setUpDataTime()
    }
—-> 4.12 退出(直接pop就可以)
    @IBAction func popVC()
    {
        navigationController?.popViewControllerAnimated(true)
    }
—-> 4.13 當前時間和歌曲總時間的處理(采用定時器)–>裡面創建定時器和方法的調用我這裡就不寫出來了
    //** 設置定時器 */
    func addTimer() {
        //** 設置定時器 */
        timer = NSTimer(timeInterval: 1, target: self, selector: "setUpDatasTimes", userInfo: nil, repeats: true)
        //** 將定時器添加到主運行循環中 */
        NSRunLoop.currentRunLoop().addTimer(timer!, forMode: NSRunLoopCommonModes)
    }

    //** 移除定時器 */
    func removeTimer() ->() {
        timer?.invalidate()
        timer = nil
    }

五 歌手頭像動畫處理(頭像旋轉)

1 頭像的暫停動畫和恢復動畫我們采用一個分類(下面的分類中的代碼 : 暫時沒研究是怎麼實現的)

extension CALayer {
    // 暫停動畫
    func pauseAnimate()
    {
        let pausedTime: CFTimeInterval = convertTime(CACurrentMediaTime(), fromLayer: nil)
        speed = 0.0;
        timeOffset = pausedTime;
    }

    // 恢復動畫
    func resumeAnimate()
    {
        let pausedTime: CFTimeInterval = timeOffset
        speed = 1.0;
        timeOffset = 0.0;
        beginTime = 0.0;
        let timeSincePause: CFTimeInterval = convertTime(CACurrentMediaTime(), fromLayer: nil) - pausedTime
        beginTime = timeSincePause;
    }
}

2 處理動畫

—-> 2.1 通過在類擴展中提供三個方法(恢復動畫;暫停動畫;添加動畫)
—-> 2.2 恢復動畫和暫停動畫
    //恢復動畫
    private func resumeAnimation() {
        foreImageView.layer.resumeAnimate()
    }
    //暫停動畫
    private func pauseAnimation() {
        foreImageView.layer.pauseAnimate()
    }
—-> 2.3 添加動畫
    private func addAnimation() {
        //移除上移個動畫
        foreImageView.layer.removeAnimationForKey("rotation")
        //添加動畫
        let animation = CABasicAnimation(keyPath: "transform.rotation.z")
        //設置相關屬性
        animation.duration = 30
        animation.fromValue = 0
        animation.toValue = M_PI * 2
        animation.repeatCount = MAXFLOAT

        //播放完成後不需要移除動畫
        animation.removedOnCompletion = false
        //添加動畫
        foreImageView.layer.addAnimation(animation, forKey: "rotation")
    }

3 動畫調用 :

—-> 3.1 用戶點擊播放和暫停按鈕的時候,需要調用
    //** 播放和暫停 */
    @IBAction func playAndPause(button : UIButton)
    {
        button.selected = !button.selected
        //判斷
        if button.selected {
            XFJQQMusicOperationTool.shareInstance.pauseCurrentMusic()
            pauseAnimation()
        }else {
            XFJQQMusicOperationTool.shareInstance.playCurrentMusic()
            resumeAnimation()
        }
    }
—-> 3.2 當用戶點擊顯示歌曲的tableView中的cell,頁面開始跳轉後需要動畫效果.(只需要設置一次)
        //將歌詞的數據源交給展示歌曲的控制器來展示
        lrcTVC.dataSource = lrcMs
        //切換歌曲開始動畫
        addAnimation()

        //判斷如果是選擇暫停和開始的屬性做相應的動畫
        if musicMessageModel.isPlaying {
            resumeAnimation()
        }else {
            pauseAnimation()
        }        

六 歌詞的展示(比較有難度)

1 封裝處理歌詞的工具類.(封裝原因 : 展示出來的數據並不符合格式,需要我們做處理)–>下圖展示的是需要處理的歌詞數據

這裡寫圖片描述

2 創建歌詞展示的模型(模型中需要的屬性 : 歌曲開始時間;歌曲結束時間;歌詞內容)

class XFJQQLrcModel: NSObject {

    //** 歌詞演唱的開始時間 */
    var beginTime : NSTimeInterval = 0
    //** 歌詞演唱的結束時間 */
    var endTime : NSTimeInterval = 0
    //** 歌詞的內容 */
    var lrcStr : String = ""
}

3 處理歌詞工具類的文件

這裡寫圖片描述

4 在該工具類中創建一個方法能返回具體哪行返回的歌詞(采用元組的方法)

    //提供一個方法對某一行歌詞的返回(需要傳入當前播放的時間進度和模型中的開始時間,結束時間)
    //采用元組的方式來達到讀取歌詞的經度
    class func getLrcMusicRow(current : NSTimeInterval, lrcModel : [XFJQQLrcModel]) ->(row :Int, lrcM : XFJQQLrcModel){
        //取出模型的個數
        let count = lrcModel.count
        //遍歷
        for i in 0.. current {

                return (i, lrcM)
            }
        }
        return (0, XFJQQLrcModel())
    }

5 設計一個方法: 當外界調用的時候傳入首歌曲的歌詞,然後經過該方法,返回一個解析好的可實現的歌詞.

—-> 5.1 處理該部分的歌詞 :
[ti:]
[ar:]
[al:]
—-> 5.2 代碼(類方法)–> 裡面包括 : 異常處理;將歌詞轉換為一行一行的顯示;過濾掉不能處理的符號;裝入模型中(該方法的上部分)
    //設計一個方法用來處理歌詞
    class func getLrcMusicData(fileName : String?) ->[XFJQQLrcModel] {
        //獲取歌詞文件的路徑
        guard let path = NSBundle.mainBundle().pathForResource(fileName, ofType: nil) else{
            return [XFJQQLrcModel]()
        }
        //加載文件的內容
        var contentLrc = ""
        do {
            contentLrc = try String(contentsOfFile: path)
        }catch {
            print(error)
            return [XFJQQLrcModel]()
        }

        //將歌詞轉成一行一行組成的數組
        let lrcArray = contentLrc.componentsSeparatedByString("\n")

        //創建一個裝XFJQQLrcModel這種類型的數組
        var lrcMs = [XFJQQLrcModel]()

        //遍歷歌詞的組成的數組,然後放入lrcMs數組中
        for lrcmStr in lrcArray {
            //過濾掉垃圾數據
            if lrcmStr.containsString("[ti:") || lrcmStr.containsString("[ar:") || lrcmStr.containsString("[al:") {
                continue
            }
            //裝入上面的數組中
            let lrcm = XFJQQLrcModel()
            lrcMs.append(lrcm)

6 通過調用處理好的歌詞的方法來處理過濾好的歌詞

[00:00.89]傳奇
[00:02.34]作詞:劉兵
[00:03.82]作曲:李健
[00:05.48]演唱:王菲
—-> 6.1 代碼 :
            //拿到的數據才是真正能解析的數據
            //替換
            let resultStr = lrcmStr.stringByReplacingOccurrencesOfString("[", withString: "")
            //開始解析
            let timeAndContent = resultStr.componentsSeparatedByString("]")
            if timeAndContent.count == 2 {
                let time = timeAndContent[0]
                lrcm.beginTime = XFJQQTimeTool.getLrcFormatTime(time)
                let content = timeAndContent[1]
                lrcm.lrcStr = content
            }
        }

        //遍歷所有的數組中的時間
        let count = lrcMs.count
        for i in 0..
—-> 6.2 對能處理的歌詞方法的調用
    //** 該方法是對歌詞的開唱時間和結束時間的處理(根據傳入的字符串,返回一個確切的時間) */
    class func getLrcFormatTime(time : String) ->NSTimeInterval {
        //根據":"取出時間
        let minAndSec = time.componentsSeparatedByString(":")
        //判斷
        if minAndSec.count == 2 {
            //分鐘
            let min = NSTimeInterval(minAndSec[0]) ?? 0
            //秒鐘
            let sec = NSTimeInterval(minAndSec[1]) ?? 0
            //返回處理好的時間
            return min * 60 + sec
        }
        //如果走到這裡,就直接返回0
        return 0
    }

7 將處理好的歌詞交給顯示歌詞的tableView來顯示

        //獲取歌詞數據源
        let lrcMs = XFJQQMusicLrcDataTool.getLrcMusicData(musicMessageModel.musicModel?.lrcname)
        //打印出歌詞
        print(lrcMs)

        //將歌詞的數據源交給展示歌曲的控制器來展示
        lrcTVC.dataSource = lrcMs

8 之間用來顯示歌詞的是UIView,現在我們使用UITableView來顯示,將使用到UIView顯示歌詞的地方全都用tableView來代替.

9 實現tableView中數據源發方法

///MARK : - 數據源方法
extension XFJQQLrcTVC {
    //組
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }
    //每組的cell
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //由模型數據決定
        return dataSource.count
    }
    //每行cell的內容
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        //用該方法得到cell
        let cell = XFJQQMusicLrcCell.getMusicLrcCell(tableView)
        //判斷如果當前處在最中間的是正在播放的行數,那麼久賦值,否則就賦值為0
        if indexPath.row == scrollRow {
            cell.progress = progress
        }else {
            cell.progress = 0.0
        }
        //取出模型
        let lrcStr = dataSource[indexPath.row]
        //賦值
        cell.lrcStr = lrcStr.lrcStr
        return cell
    }
}

10 自定義cell和自定義顯示歌詞的label

—-> 10.1 自定義cell(該部分是對cell中label的顯示)
    @IBOutlet weak var lrcLabel: XFJQQMusicLrcLabel!

    //提供一個屬性給展示歌詞的view中的歌詞狀態
    var progress : Double = 0.0 {
        didSet {
             lrcLabel.progress = progress
        }
    }

    var lrcStr : String = "" {
        didSet {
            lrcLabel.text = lrcStr
        }
    }
}
—-> 10.2 返回創建好的cell
///MARK : - 再累擴展中提供一個方法,返回cell
extension XFJQQMusicLrcCell {
    class func getMusicLrcCell(tableView : UITableView) ->XFJQQMusicLrcCell {
        let lrcCellID = "lrcCell"
        var cell = tableView.dequeueReusableCellWithIdentifier(lrcCellID) as? XFJQQMusicLrcCell
        if cell == nil {
            cell = NSBundle.mainBundle().loadNibNamed("XFJQQMusicLrcCell", owner: nil, options: nil).first as? XFJQQMusicLrcCell
        }
        return cell!
    }
}
—-> 10.3 自定義label
class XFJQQMusicLrcLabel: UILabel {

    //自定義更新歌詞的進度(提供set方法)
    var progress : Double = 0.0 {
        didSet {
            //重繪
            setNeedsDisplay()
        }
    }
    override func drawRect(rect: CGRect) {
        super.drawRect(rect)
        //設置填充顏色
        UIColor.greenColor().set()
        let progressloat = CGFloat(progress)

        let rect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width * progressloat, rect.size.height)

        UIRectFillUsingBlendMode(rect, CGBlendMode.SourceIn)
    }
}

11 當有歌詞歌曲變化的時候,立刻更新歌詞的數據

    var dataSource : [XFJQQLrcModel] = [XFJQQLrcModel]() {

        didSet {
            tableView.reloadData()
        }
    }

12 在顯示歌詞的tableView控制器中設置一個屬性用來提供正在歌唱的歌詞始終處於tableView的中間cell

    //設置歌詞滾動到中間(set方法)
    var scrollRow : Int = 0 {
        didSet {
            //判斷防止重復滾動(用舊值作為判斷)
            if scrollRow != oldValue {

                tableView.reloadRowsAtIndexPaths(tableView.indexPathsForVisibleRows!, withRowAnimation: UITableViewRowAnimation.Fade)
                let indexPath = NSIndexPath(forRow: scrollRow, inSection: 0)
                //拿到角標滾動到哪個位置
                tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Middle, animated: true)
                //刷新(如果先做動畫再刷新的話,動畫還沒做完就直接刷新了,會出現顯示歌詞的view跳動,所以需要先刷新再動畫)
//                tableView.reloadRowsAtIndexPaths(tableView.indexPathsForVisibleRows!, withRowAnimation: UITableViewRowAnimation.Fade)

            }
        }
    }

13 給正在歌唱的cell中的歌詞設置進度(set方法)

    var progress : Double = 0.0 {
        didSet {
            //獲取當前正在行號
            let indexPath = NSIndexPath(forRow: scrollRow, inSection: 0)
            //將當前的cell類型轉換
            let cell = tableView.cellForRowAtIndexPath(indexPath) as? XFJQQMusicLrcCell
            //給cell中progress賦值
            cell?.progress = progress
        }
    }

14 處理已進入展示歌詞的頁面,歌詞的頭部位置處於tableView的中間部位

    //在view將要布局的時候對顯示歌詞的view布局,讓其頭部顯示在中間
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        tableView.contentInset = UIEdgeInsets(top: tableView.height * 0.5, left: 0, bottom: tableView.height * 0.5, right: 0)
    }

15 更新滾動時候的歌詞(該方法調用頻繁)

    //更新滾動的時候歌詞(調用頻率頻繁)
     func updateLrc () ->() {
        //獲取歌曲的最新值
        let musicMessageModel = XFJQQMusicOperationTool.shareInstance.getUpNewMusicMessage()
        //獲取最新歌詞的行號
        let rowLrm = XFJQQMusicLrcDataTool.getLrcMusicRow(musicMessageModel.costTime, lrcModel:lrcTVC.dataSource)
        let row = rowLrm.row
        //賦值
        lrcTVC.scrollRow = row

        //給歌詞標簽展示歌詞
        let lrcm = rowLrm.lrcM
        lrcLabel.text = lrcm.lrcStr
        //歌詞進度(當前的進度除以在總進度)
        let value = (musicMessageModel.costTime - lrcm.beginTime) / (lrcm.endTime - lrcm.beginTime)
        //賦值

        lrcLabel.progress = value

        //給展示歌詞的view賦值
        lrcTVC.progress = value

16 怎麼才能讓歌詞滾動呢? 通過系統的一個類CADisplayLink(和定時器作用差不多,這裡我代碼就不寫上了)

七 注意點和性能優化

1 注意 : 退出後台動畫不再旋轉—> 解決方案 : 動畫完成之後,不需要移除

2 怎麼樣將歌詞分割成一行一行,然後展示呢?—>解決方案 : 通過設置一個歌詞模型來展示

3 歌詞不滾動?—> 解決方案 : CADisplayLink(類似定時器)

4 歌詞顯示的時候出現了刷新問題?—> 解決方案 : 先刷新,在滾動

5 性能優化 : 圖片繪制的次數太多?

—-> 5.1 解決方案 : 通過設置一個屬性記錄歌詞的行值,然後判斷是否是同一行

6 當前顯示的時間一直在更新,暫停的時候不需要更新,也可以優化(留給你們實現了)

八 功能補充(額外的想法,還未實現)

1 拖動進度條達到快進的目的

2 後台模式(後面會抽時間補上)

3 搖一搖切換歌曲

九 總結

1 該篇博客寫的思路還算清晰,唯一的缺點是我無法在後面歌詞顯示部分更加詳細點說明,因為該處真是沒辦法說明了,只能奉上我寫的代碼了.

2 本篇博客是基於QQ音樂的swift版本,還有很多的功能沒有實現,希望後面我能抽出時間進一步的完善也希望閱讀過我博客的程序猿能提供意見.

3 最後,由於時間一直沒有抽出來,這使得博客更新的速度有點慢,後續我會慢慢補上.如果大家覺的我寫的還可以,麻煩大家關注我的官方博客,謝謝!!!!

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved