上一篇文章讲到歌词处理(时间、歌词的截取),接下来将歌词显示到视图
实现的大概流程:
歌词与进度条上显示的时间一样,需要实时的去更新,所以
1.封装一个更新歌词的方法,在定时器方法中实时调用
2.声明一个全局的属性,用来记录当前歌词的索引,通过索引取出当前句歌词赋值
// 更新歌词
- (void)updateLyric{
// 当前歌词
JSLyricModel *currentLyric = self.lyricModelArray[self.currentLyricIndex];
// 下一句歌词 ( 2.判断越界问题)
JSLyricModel *nextLyric = nil;
if (self.currentLyricIndex == self.lyricModelArray.count - 1) {
// 创建一个最大的下一句歌词
nextLyric = [[JSLyricModel alloc]init];
// 给自定义出来的最后一条歌词设置数据 (设置成最后一条歌词的数据)
nextLyric.content = currentLyric.content;
// 因为当前索引已经是最后一条歌词,所以上面的歌词赋值就相当于nextLyric.content = [self.lyricModelArray lastObject].content;
// 直接设置成歌曲的总时长
nextLyric.initialTime = [JSMusciManager sharedMusicManager].duration;
}else{
nextLyric = self.lyricModelArray[self.currentLyricIndex + 1];
}
// 正向调整进度(判断越界问题): 判断时间,改变当前的歌词的索引 : 当前播放时间 > 下一句歌词的起始时间 歌词索引 +1
if ([JSMusciManager sharedMusicManager].currentTime > nextLyric.initialTime && self.currentLyricIndex < self.lyricModelArray.count - 1) {
self.currentLyricIndex++;
// 拖拽进度条时,只需要显示最近当前歌词,防止拖动歌词逐条跳动
[self updateLyric];
// 1. 当累加到正确的当前歌词索引时,下面才给歌词赋值,否则递归调用返回
return;
// 如果不进行递归调用直接return: 这里更新数据的定时器间隔时间为0.1s,假如将进度条拖拽到歌词索引60的位置,那么等到定时器自动调用到到歌词索引为60的歌词数据时,需要6s的时间才可以
}
// 反向调整进度(判断越界问题): 当前时间 < 当前句歌词的初始时间 歌词索引-1
if ([JSMusciManager sharedMusicManager].currentTime < currentLyric.initialTime && self.currentLyricIndex > 0) {
self.currentLyricIndex--;
[self updateLyric];
return;
}
self.verticalLyricLabel.text = self.lyricModelArray[self.currentLyricIndex].content;
}
需要考虑的点有:
- 调整进度条切歌:
先进行递归调用,如果自增得到的该条歌词索引不是我们调整进度条所在歌词的索引,直接return返回,不进行歌词赋值
[self updateLyric];// 调用自己
return;
如果不进行递归调用直接return: 这里更新数据的定时器间隔时间为0.1s,假如将进度条拖拽到歌词索引60的位置,那么等到定时器自动调用到到歌词索引为60的歌词数据时,需要6s的时间才可以,所以需要通过递归调用的方式,直到找到正确的歌词索引后不满足自增或自减条件了,进行歌词赋值,及时的在视图上同步歌词
- 歌词数组越界:
上面的代码中直接使用了所以进行了判断,假设这首歌有60句歌词,已经到了第60句,再次自加就会出现越界问题,所以只有当当前歌词索引小于(数组长度-1)的时候才进行自加,同理,反向调整进度条时,只有当当前歌词索引大于零时才进行自减
当"当前歌词"索引为最后一条时,下面需要使用下一条歌词来判断,所以这里设置一条虚拟的最后一条歌词模型
if (self.currentLyricIndex == self.lyricModelArray.count - 1) {
// 创建一个最大的下一句歌词 (虚拟数据)
nextLyric = [[JSLyricModel alloc]init];
// 给自定义出来的最后一条歌词设置数据 (设置成最后一条歌词的数据)
nextLyric.content = currentLyric.content;
// 因为当前索引已经是最后一条歌词,所以上面的歌词赋值就相当于nextLyric.content = [self.lyricModelArray lastObject].content;
// 直接设置成歌曲的总时长
nextLyric.initialTime = [JSMusciManager sharedMusicManager].duration;
}
下面的判断处理需要一个下一条歌词:
if ([JSMusciManager sharedMusicManager].currentTime > nextLyric.initialTime && self.currentLyricIndex < self.lyricModelArray.count - 1)
这里先给最后一条虚拟的歌词模型设置了属性,从判断条件来看,暂时这里还用不到最后一条虚拟歌词的数据,后面的设置歌词根据进度变色会用到
- 切歌后的索引越界
前面对当前播放歌曲的歌词索引进行了越界判断,不同歌曲的歌词不同,所以索引值不同,防止切歌后索引混乱甚至越界,在点击切换歌曲按钮后,要将索引清零
(上一曲、下一曲按钮点击事件中)
// 切歌索引清零
self.currentLyricIndex = 0;