上一篇文章講到歌詞處理(時(shí)間最岗、歌詞的截取),接下來將歌詞顯示到視圖
實(shí)現(xiàn)的大概流程:
歌詞與進(jìn)度條上顯示的時(shí)間一樣,需要實(shí)時(shí)的去更新,所以
1.封裝一個(gè)更新歌詞的方法,在定時(shí)器方法中實(shí)時(shí)調(diào)用
2.聲明一個(gè)全局的屬性,用來記錄當(dāng)前歌詞的索引,通過索引取出當(dāng)前句歌詞賦值
// 更新歌詞
- (void)updateLyric{
// 當(dāng)前歌詞
JSLyricModel *currentLyric = self.lyricModelArray[self.currentLyricIndex];
// 下一句歌詞 ( 2.判斷越界問題)
JSLyricModel *nextLyric = nil;
if (self.currentLyricIndex == self.lyricModelArray.count - 1) {
// 創(chuàng)建一個(gè)最大的下一句歌詞
nextLyric = [[JSLyricModel alloc]init];
// 給自定義出來的最后一條歌詞設(shè)置數(shù)據(jù) (設(shè)置成最后一條歌詞的數(shù)據(jù))
nextLyric.content = currentLyric.content;
// 因?yàn)楫?dāng)前索引已經(jīng)是最后一條歌詞,所以上面的歌詞賦值就相當(dāng)于nextLyric.content = [self.lyricModelArray lastObject].content;
// 直接設(shè)置成歌曲的總時(shí)長
nextLyric.initialTime = [JSMusciManager sharedMusicManager].duration;
}else{
nextLyric = self.lyricModelArray[self.currentLyricIndex + 1];
}
// 正向調(diào)整進(jìn)度(判斷越界問題): 判斷時(shí)間,改變當(dāng)前的歌詞的索引 : 當(dāng)前播放時(shí)間 > 下一句歌詞的起始時(shí)間 歌詞索引 +1
if ([JSMusciManager sharedMusicManager].currentTime > nextLyric.initialTime && self.currentLyricIndex < self.lyricModelArray.count - 1) {
self.currentLyricIndex++;
// 拖拽進(jìn)度條時(shí),只需要顯示最近當(dāng)前歌詞,防止拖動歌詞逐條跳動
[self updateLyric];
// 1. 當(dāng)累加到正確的當(dāng)前歌詞索引時(shí),下面才給歌詞賦值,否則遞歸調(diào)用返回
return;
// 如果不進(jìn)行遞歸調(diào)用直接return: 這里更新數(shù)據(jù)的定時(shí)器間隔時(shí)間為0.1s,假如將進(jìn)度條拖拽到歌詞索引60的位置,那么等到定時(shí)器自動調(diào)用到到歌詞索引為60的歌詞數(shù)據(jù)時(shí),需要6s的時(shí)間才可以
}
// 反向調(diào)整進(jìn)度(判斷越界問題): 當(dāng)前時(shí)間 < 當(dāng)前句歌詞的初始時(shí)間 歌詞索引-1
if ([JSMusciManager sharedMusicManager].currentTime < currentLyric.initialTime && self.currentLyricIndex > 0) {
self.currentLyricIndex--;
[self updateLyric];
return;
}
self.verticalLyricLabel.text = self.lyricModelArray[self.currentLyricIndex].content;
}
需要考慮的點(diǎn)有:
- 調(diào)整進(jìn)度條切歌:
先進(jìn)行遞歸調(diào)用,如果自增得到的該條歌詞索引不是我們調(diào)整進(jìn)度條所在歌詞的索引,直接return返回,不進(jìn)行歌詞賦值
[self updateLyric];// 調(diào)用自己
return;
如果不進(jìn)行遞歸調(diào)用直接return: 這里更新數(shù)據(jù)的定時(shí)器間隔時(shí)間為0.1s,假如將進(jìn)度條拖拽到歌詞索引60的位置,那么等到定時(shí)器自動調(diào)用到到歌詞索引為60的歌詞數(shù)據(jù)時(shí),需要6s的時(shí)間才可以,所以需要通過遞歸調(diào)用的方式,直到找到正確的歌詞索引后不滿足自增或自減條件了,進(jìn)行歌詞賦值,及時(shí)的在視圖上同步歌詞
- 歌詞數(shù)組越界:
上面的代碼中直接使用了所以進(jìn)行了判斷,假設(shè)這首歌有60句歌詞,已經(jīng)到了第60句,再次自加就會出現(xiàn)越界問題,所以只有當(dāng)當(dāng)前歌詞索引小于(數(shù)組長度-1)的時(shí)候才進(jìn)行自加,同理,反向調(diào)整進(jìn)度條時(shí),只有當(dāng)當(dāng)前歌詞索引大于零時(shí)才進(jìn)行自減
當(dāng)"當(dāng)前歌詞"索引為最后一條時(shí),下面需要使用下一條歌詞來判斷,所以這里設(shè)置一條虛擬的最后一條歌詞模型
if (self.currentLyricIndex == self.lyricModelArray.count - 1) {
// 創(chuàng)建一個(gè)最大的下一句歌詞 (虛擬數(shù)據(jù))
nextLyric = [[JSLyricModel alloc]init];
// 給自定義出來的最后一條歌詞設(shè)置數(shù)據(jù) (設(shè)置成最后一條歌詞的數(shù)據(jù))
nextLyric.content = currentLyric.content;
// 因?yàn)楫?dāng)前索引已經(jīng)是最后一條歌詞,所以上面的歌詞賦值就相當(dāng)于nextLyric.content = [self.lyricModelArray lastObject].content;
// 直接設(shè)置成歌曲的總時(shí)長
nextLyric.initialTime = [JSMusciManager sharedMusicManager].duration;
}
下面的判斷處理需要一個(gè)下一條歌詞:
if ([JSMusciManager sharedMusicManager].currentTime > nextLyric.initialTime && self.currentLyricIndex < self.lyricModelArray.count - 1)
這里先給最后一條虛擬的歌詞模型設(shè)置了屬性,從判斷條件來看,暫時(shí)這里還用不到最后一條虛擬歌詞的數(shù)據(jù),后面的設(shè)置歌詞根據(jù)進(jìn)度變色會用到
- 切歌后的索引越界
前面對當(dāng)前播放歌曲的歌詞索引進(jìn)行了越界判斷,不同歌曲的歌詞不同,所以索引值不同,防止切歌后索引混亂甚至越界,在點(diǎn)擊切換歌曲按鈕后,要將索引清零
(上一曲廷臼、下一曲按鈕點(diǎn)擊事件中)
// 切歌索引清零
self.currentLyricIndex = 0;