QQ音樂(lè)播放器,歌詞同步

源代碼下載路徑:https://pan.baidu.com/s/1dES8wfR?因?yàn)槔锩娲a中包含的資源過(guò)多,沒(méi)有上傳到我的github賬號(hào)中,直接保存在百度云盤(pán)中。

? ? ? ?這兩天工作上沒(méi)什么事,模仿QQ音樂(lè)播放器寫(xiě)了個(gè)簡(jiǎn)單的QQ音樂(lè)播放界面,可以實(shí)現(xiàn)歌詞同步功能。另外這個(gè)Demo中還設(shè)置了后臺(tái)鎖屏播放界面模式,處于鎖屏狀態(tài)下同樣可以像QQ音樂(lè)那樣自如切換,以及顯示歌詞。

? ? ? ? 看一下震撼的效果圖:


效果圖

? ? ? ?接下來(lái)這篇文章主要是分析一下本人認(rèn)為有必要說(shuō)明的幾個(gè)點(diǎn)。分別是:滑動(dòng)的時(shí)候顯示歌詞界面問(wèn)題、歌詞按照音樂(lè)播放的進(jìn)度逐漸顯示為綠色的實(shí)現(xiàn)、播放界面imageView旋轉(zhuǎn)和暫停動(dòng)畫(huà)問(wèn)題、鎖屏界面信息配置。可能有人認(rèn)為控制播放界面imageView旋轉(zhuǎn)和暫停動(dòng)畫(huà)是非常簡(jiǎn)單的事情,確實(shí)簡(jiǎn)單,但是有沒(méi)有想過(guò)如何通過(guò)核心動(dòng)畫(huà)去控制動(dòng)畫(huà)的暫停和開(kāi)始。

1.如何在手指向右滑動(dòng)的時(shí)候顯示歌詞界面?

? ? ? 這個(gè)其實(shí)很簡(jiǎn)單,但是如果沒(méi)有做過(guò)類(lèi)似這樣app的開(kāi)發(fā)人員,可能認(rèn)為就是在界面上添加一個(gè)滑動(dòng)的手勢(shì),然后通過(guò)判斷手勢(shì)的滑動(dòng)方向,來(lái)控制歌詞界面的展示和隱藏。這樣做雖然可以實(shí)現(xiàn)同樣的目的,但是會(huì)過(guò)于麻煩。最好的做法是借助UIScrollView控件,直接通過(guò)劃過(guò)scroollView來(lái)展示和隱藏歌詞界面,這種做法干脆利落簡(jiǎn)便。目前很火熱的一些直播類(lèi)app的聊天互動(dòng)界面其實(shí)也都是通過(guò)這樣的方式完成的。在滑動(dòng)scrooView的時(shí)候,我們還可以通過(guò)scroollView的代理方法設(shè)置播放界面的透明度,使界面更加美觀。

2.如何通過(guò)核心動(dòng)畫(huà)控制播放界面imageView旋轉(zhuǎn)和暫停動(dòng)畫(huà)?

? ? ? ?可能以前用核心動(dòng)畫(huà)的時(shí)候一直沒(méi)有涉及到動(dòng)畫(huà)的暫停和開(kāi)始,可是當(dāng)我用核心動(dòng)畫(huà)來(lái)設(shè)置動(dòng)畫(huà)效果,當(dāng)音樂(lè)播放暫停的時(shí)候要停止動(dòng)畫(huà)效果。這時(shí)一下子就懵了,怎樣實(shí)現(xiàn)呢。于是在網(wǎng)上找到了解決方案。正確的做法是創(chuàng)建一個(gè)CALayer的分類(lèi),然后再源文件中實(shí)現(xiàn)以下代碼:

- (void)pauseAnimate

{

? ? ? ? CFTimeInterval pausedTime = [self convertTime:CACurrentMediaTime() fromLayer:nil];

? ? ? ? self.speed = 0.0;

? ? ? ? self.timeOffset = pausedTime;

}

- (void)resumeAnimate

{

? ? ? ? ? ?CFTimeInterval pausedTime = [self timeOffset];

? ? ? ? ?self.speed = 1.0;

? ? ? ? ?self.timeOffset = 0.0;

? ? ? ? ? self.beginTime = 0.0;

? ? ? ? ? ?CFTimeInterval timeSincePause = [self convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;

? ? ? ? self.beginTime = timeSincePause;

}

? ? ? ?上面第一個(gè)方法是暫停動(dòng)畫(huà),第二個(gè)方法是開(kāi)始動(dòng)畫(huà)。這個(gè)類(lèi)別可以保存起來(lái),以后碰到其他類(lèi)似問(wèn)題,照舊可以拿來(lái)使用。

3.歌詞如何實(shí)現(xiàn)和播放的進(jìn)度同步?

? ? ? 這里主要講解綠色文字如何和歌詞實(shí)現(xiàn)同步。至于每一句歌詞如何和歌詞同步就簡(jiǎn)單說(shuō)下,主要是通過(guò)定時(shí)器完成,要解析歌詞每一句對(duì)應(yīng)的時(shí)間和文字。綠色文字的同步看起來(lái)課高大上,實(shí)際上很簡(jiǎn)單,代碼量也就簡(jiǎn)短的數(shù)行。首先要知道,每一行歌詞是借助UILabel顯示的,要想事項(xiàng)綠色文字和歌詞同步,我們只需要自定義自己的label類(lèi)即可,但是毋庸置疑這個(gè)自定的這個(gè)label類(lèi)要有一個(gè)進(jìn)度progress屬性。看一下這個(gè)自定義label的源碼。

.h文件實(shí)現(xiàn)

#import@interface ZWLrcLabel : UILabel

/*當(dāng)前播放的進(jìn)度*/

@property(nonatomic,assign)CGFloat progress;

@end

.m文件實(shí)現(xiàn)

#import "ZWLrcLabel.h"

@implementation ZWLrcLabel

- (void)drawRect:(CGRect)rect {

? ? ? ? ?[super drawRect:rect];?

? ? ? ? CGRect fillRect = CGRectMake(0, 0, self.bounds.size.width * self.progress, self.bounds.size.height);

? ? ? [[UIColor greenColor] set];

? ? ? // UIRectFill(fillRect);

? ? ? ?UIRectFillUsingBlendMode(fillRect, kCGBlendModeSourceIn);

}

- (void)setProgress:(CGFloat)progress{

? ? ? ? ?_progress = progress;

? ? ? ? [self setNeedsDisplay];

}

代碼中UIRectFillUsingBlendMode(fillRect, kCGBlendModeSourceIn);是實(shí)現(xiàn)播放進(jìn)度和綠色歌詞文字同步的核心。UIRectFill(fillRect);是label背景色的變化,這行代碼用不到,在這里只是提一下,有興趣的可以看看具體實(shí)現(xiàn)效果。調(diào)用[self setNeedsDisplay];這句代碼就會(huì)調(diào)用- (void)drawRect:(CGRect)rect方法。

4.鎖屏狀態(tài)歌曲播放切換,以及界面顯示是如何自定義的?

首先要想實(shí)現(xiàn)歌詞鎖屏狀態(tài)界面的相關(guān)配置,首先必然要開(kāi)啟后臺(tái)音頻回話。應(yīng)該在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;添加以下三行代碼:

? ? ? ? //1.獲取音頻會(huì)話

? ? ? ?AVAudioSession *session = [AVAudioSession sharedInstance];

? ? ? ? //2.設(shè)置后臺(tái)類(lèi)型

? ? ? [session setCategory:AVAudioSessionCategoryPlayback error:nil];

? ? ? ?//3.激活回話

? ? ? ?[session setActive:YES error:nil];

? ? ? 接下來(lái),先看一下鎖屏界面信息(如圖片,歌曲名,歌手名,時(shí)長(zhǎng)等)配置是如何實(shí)現(xiàn)的,代碼中有注釋。以下代碼在歌曲開(kāi)始播放的時(shí)候,直接調(diào)用即可。

- (void)setupLockScreenInfo{

? ? ? ? ?//0.獲取當(dāng)前播放的歌曲

? ? ? ? ZWMusicModel *playingMusic = [ZWMusicTool playingMusic];

? ? ? ?//1.獲取鎖屏中心

? ? ? ?MPNowPlayingInfoCenter *playingInfoCenter = [MPNowPlayingInfoCenter defaultCenter];?

? ? ? ?//2、設(shè)置屏幕參數(shù)

? ? ? ? NSDictionary *playingInfoDict = [NSMutableDictionary dictionary];

? ? ? ?//2.1設(shè)置歌曲名

? ? ? ?[playingInfoDict setValue:playingMusic.name forKey:MPMediaItemPropertyAlbumTitle];

? ? ? //2.2設(shè)置歌手名

? ? ? ?[playingInfoDict setValue:playingMusic.singer forKey:MPMediaItemPropertyArtist];

? ? ? ?//2.3設(shè)置封面圖片?

? ? ? ?MPMediaItemArtwork *artWork = [[MPMediaItemArtwork alloc]initWithImage:[UIImage imageNamed:playingMusic.icon]];

? ? ? ?[playingInfoDict setValue:artWork forKey:MPMediaItemPropertyArtwork];

? ? ? ?//2.4歌曲的總時(shí)長(zhǎng)

? ? ? ?[playingMusic setValue:@(self.currentPlayer.duration) forKey:MPMediaItemPropertyPlaybackDuration];

? ? ? ?playingInfoCenter.nowPlayingInfo = playingInfoDict;

? ? ? ? //3.開(kāi)啟遠(yuǎn)程交互

? ? ? ?[[UIApplication sharedApplication]beginReceivingRemoteControlEvents];

}

最后再來(lái)看看如何實(shí)現(xiàn)后臺(tái)的遠(yuǎn)程交互,控制音樂(lè)的播放暫停,下一曲等。這里要注意兩點(diǎn):a、- (void)remoteControlReceivedWithEvent:(UIEvent *)event是一個(gè)系統(tǒng)方法。b、要想要這個(gè)系統(tǒng)方法生效,在配置鎖屏界面UI相關(guān)信息的時(shí)候,要開(kāi)啟遠(yuǎn)程交互,即[[UIApplication sharedApplication]beginReceivingRemoteControlEvents];

- (void)remoteControlReceivedWithEvent:(UIEvent *)event{

? ? ? ?switch (event.subtype) {

? ? ? ? ? ? ? ? ? case UIEventSubtypeRemoteControlPlay:

? ? ? ? ? ? ? ? ? case UIEventSubtypeRemoteControlPause:

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [self playOrPause:self.playButton];//播放或暫停的方法

? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ?case UIEventSubtypeRemoteControlNextTrack:?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [self next:self.nextButton];//下一曲的方法

? ? ? ? ? ? ? ? ?break;

? ? ? ? ? ? ? ? ?case? UIEventSubtypeRemoteControlPreviousTrack:

? ? ? ? ? ? ? ? ? ? ? ? ? [self next:self.previousButton];//上一曲的方法

? ? ? ? ? ? ? ? ?break;

? ? ? ? ? ? ? ? ?default:

? ? ? ? ? ? ? ? ?break;

? ? ? }

}

就簡(jiǎn)單介紹到這里,源代碼中有注釋?zhuān)梢越Y(jié)合這篇文章和源代碼一塊學(xué)習(xí)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,428評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,024評(píng)論 3 413
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,285評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,548評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,328評(píng)論 6 404
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 54,878評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,971評(píng)論 3 439
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,098評(píng)論 0 286
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,616評(píng)論 1 331
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,554評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,725評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,243評(píng)論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,971評(píng)論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,361評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,613評(píng)論 1 280
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,339評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,695評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容