最近朋友想做个音乐App,让我帮忙参考下。其中歌词动态滚动的效果,正好我之前也没做过,顺便学习一下,先来个预览效果。

实现思路

歌词常见的就是lrc歌词了,我们这里也是通过解析lrc歌词文件来获取其播放参数,以实现和播放器协同。下面是我从百度音乐获取的歌词文件示例:

[ti:冰雨]
[ar:刘德华]
[al:笨小孩]
[:0.05]冰雨
[:0.94]作词:刘德华、李密 作曲:潘协庆
[:01.23]演唱:刘德华 [:01.37]
[:04.79](歌手独白)
[:17.18]我是在等待 一个女孩
[:25.18]还是在等待沉沦苦海
[:32.91]一个人静静发呆 没有人去管花谢花开
[:41.03]无法肯定的爱 左右摇摆
[:45.43]只好把心酸往深心里塞
[:49.61]我是在等待 你的回来
[:57.73]难道只换回一句活该
[:05.27]一个人静静发呆
[:09.18]两个人却有不同无奈
[:13.15]好好的一份爱 啊怎么会慢慢变坏
[:18.43]
[:20.44]冷冷的冰雨在脸上胡乱的拍
[:24.31]暖暖的眼泪跟寒雨混成一块
[:28.32]眼前的色彩忽然被掩盖
[:32.28]你的影子无情在身边徘徊
[:36.30]你就像一个刽子手把我出卖
[:40.35]我的心彷佛被剌刀狠狠地宰
[:44.36]在悬崖上的爱 谁会愿意接受最痛的意外
[:51.09]
[:26.59]我是在等待你的回来
[:35.52]难道只换回一句活该
[:42.99]一个人静静发呆
[:46.99]两个人却有不同无奈
[:51.08]好好的一份爱 啊怎么会慢慢变坏
[:56.42]
[:58.54]冷冷的冰雨在脸上胡乱的拍
[:02.41]暖暖的眼泪跟寒雨混成一块
[:06.39]眼前的色彩忽然被掩盖
[:10.31]你的影子无情在身边徘徊
[:14.23]你就像一个刽子手把我出卖
[:18.34]我的心彷佛被剌刀狠狠地宰
[:22.33]在悬崖上的爱 谁会愿意接受最痛的意外
[:28.66]
[:34.57]冷冷的冰雨在脸上胡乱的拍
[:38.33]暖暖的眼泪跟寒雨混成一块
[:42.31]眼前的色彩忽然被掩盖
[:46.32]你的影子无情在身边徘徊
[:50.27]你就像一个刽子手把我出卖
[:54.34]我的心彷佛被剌刀狠狠地宰
[:58.34]悬崖上的爱 谁会敢去采
[:02.37]还是愿意接受最痛的意外 最爱的女孩
[:08.85]
[:19.72]悬崖上的爱 谁会敢去采
[:31.84]还是愿意接受最痛的意外 最爱的女孩
[:51.75]
[:10.60]歌手独白
[:16.76]

解析lrc歌词

这可能是最常见的格式了,每行为一句歌词,[]括号内为歌词对应的时间区间,所以我们首先要做的事情就是将他们提取分离出来,分别作为时间参数数组和歌词内容数组。这里我参考了一些博客的方法,解析lrc文件的代码如下:

#import <Foundation/Foundation.h>

@interface LrcParser : NSObject

//时间
@property (nonatomic,strong) NSMutableArray *timerArray;
//歌词
@property (nonatomic,strong) NSMutableArray *wordArray; //解析歌词
-(void) parseLrc;
//解析歌词
-(void) parseLrc:(NSString*)lrc;
@end

实现代码

@implementation LrcParser

-(instancetype) init{
self=[super init];
if(self!=nil){
self.timerArray=[[NSMutableArray alloc] init];
self.wordArray=[[NSMutableArray alloc] init];
}
return self;
} -(NSString *)getLrcFile:(NSString *)lrc{
NSString* filePath=[[NSBundle mainBundle] pathForResource:lrc ofType:@"lrc"];
return [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
}
//测试示例
-(void)parseLrc{
[self parseLrc:[self getLrcFile:@"冰雨"]];
} -(void)parseLrc:(NSString *)lrc{
NSLog(@"%@",lrc); if(![lrc isEqual:nil]){
NSArray *sepArray=[lrc componentsSeparatedByString:@"["];
NSArray *lineArray=[[NSArray alloc] init];
for(int i=;i<sepArray.count;i++){
if([sepArray[i] length]>){
lineArray=[sepArray[i] componentsSeparatedByString:@"]"];
if(![lineArray[] isEqualToString:@"\n"]){
[self.timerArray addObject:lineArray[]]; [self.wordArray addObject:lineArray.count>?lineArray[]:@""];
}
}
}
}
}
@end

经过测试,可以将歌词顺利解析出来,下面我们要将获得歌词数据应用于控制器。

实现动态歌词页面

看了QQ音乐的滚动歌词页面后,可以知道是借助UITableView或者UIScrollView来实现的,这里我们采用UITableView来实现动态歌词界面。

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//歌词TableView代理
self.lrcTable.delegate=self;
self.lrcTable.dataSource=self; //解析歌词
self.lrcContent=[[LrcParser alloc] init];
[self.lrcContent parseLrc];
[self.lrcTable reloadData];
//初始化播放器
[self initPlayer];
//监听播放器状态
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateTime) userInfo:nil repeats:YES];
//载入歌词背景
UIImage *img=[UIImage imageNamed:@"wall1.jpg"]; UIImageView *bgView=[[UIImageView alloc] initWithImage:[self getBlurredImage:img]]; self.lrcTable.backgroundView=bgView; }
//cell委托
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell=[self.lrcTable dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath]; cell.textLabel.text=self.lrcContent.wordArray[indexPath.row]; if(indexPath.row==_currentRow) cell.textLabel.textColor = [UIColor redColor]; else cell.textLabel.textColor = [UIColor whiteColor]; cell.textLabel.textAlignment = NSTextAlignmentCenter; cell.textLabel.font = [UIFont systemFontOfSize:]; cell.backgroundColor=[UIColor clearColor]; return cell; }

这里歌词列表的背景我采用了高斯模糊的图片,高斯模糊的方法如下:

//实现高斯模糊
-(UIImage *)getBlurredImage:(UIImage *)image{
CIContext *context = [CIContext contextWithOptions:nil];
CIImage *ciImage=[CIImage imageWithCGImage:image.CGImage];
CIFilter *filter=[CIFilter filterWithName:@"CIGaussianBlur"];
[filter setValue:ciImage forKey:kCIInputImageKey];
[filter setValue:@5.0f forKey:@"inputRadius"];
CIImage *result=[filter valueForKey:kCIOutputImageKey];
CGImageRef ref=[context createCGImage:result fromRect:[result extent]];
return [UIImage imageWithCGImage:ref];
}

播放器则采用AVPlayer,其定义和初始化设置如下:

@interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>

@property (nonatomic,strong) AVAudioPlayer *player;

@end
-(void) initPlayer{
AVAudioSession *session=[AVAudioSession sharedInstance];
[session setActive:YES error:nil];
[session setCategory:AVAudioSessionCategoryPlayback error:nil]; [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; self.player=[[AVAudioPlayer alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"冰雨" withExtension:@"mp3"] error:nil];
//单曲循环
self.player.numberOfLoops=;
[self.player prepareToPlay];
[self.player play]; }

这样就为应用定义了一个音乐播放器,下面要监听播放器的时间参数,来载入对应的歌词,如下:

[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateTime) userInfo:nil repeats:YES];

根据时间更新UI

-(void) updateTime{
CGFloat currentTime=self.player.currentTime;
NSLog(@"%d:%d",(int)currentTime / , (int)currentTime % );
for (int i=; i<self.lrcContent.timerArray.count; i++) {
NSArray *timeArray=[self.lrcContent.timerArray[i] componentsSeparatedByString:@":"];
float lrcTime=[timeArray[] intValue]*+[timeArray[] floatValue];
if(currentTime>lrcTime){
_currentRow=i;
}else
break;
} [self.lrcTable reloadData];
[self.lrcTable scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:_currentRow inSection:] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}

最后编译运行,就会发现一个滚动歌词播放器就实现啦。

完整Demo项目地址:https://github.com/ChangweiZhang/AudioPlayerDemo

iOS开发手记-仿QQ音乐播放器动态歌词的实现的更多相关文章

  1. 基于jQuery仿QQ音乐播放器网页版代码

    基于jQuery仿QQ音乐播放器网页版代码是一款黑色样式风格的网页QQ音乐播放器样式代码.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div class="m ...

  2. iOS多种刷新样式、音乐播放器、仿抖音视频、旅游App等源码

    iOS精选源码 企业级开源项目,模仿艺龙旅行App 3D立体相册,可以旋转的立方体 横竖屏切换工具,使用陀螺仪检测手机设备方向,锁屏状... Swift版Refresh(可以自定义多种样式)架构方面有 ...

  3. iOS-自定义Model转场动画-仿酷我音乐播放器效果

    周末,闲来无事,仿写了酷我音乐播放器效果: 效果图如下: 实现思路: 1.实现手势处理视图旋转 2.自定义Model动画: 1.手势是利用了一个UIPanGestureRecognizer手势: 注意 ...

  4. Android开发实战之简单音乐播放器

    最近开始学习音频相关.所以,很想自己做一个音乐播放器,于是,花了一天学习,将播放器的基本功能实现了出来.我觉得学习知识点还是蛮多的,所以写篇博客总结一下关于一个音乐播放器实现的逻辑.希望这篇博文对你的 ...

  5. iOS电商常见动画与布局、微信悬浮窗、音乐播放器、歌词解析、拖动视图等源码

    iOS精选源码 MXScroll 介绍 混合使用UIScrollView ios 电商demo(实现各种常见动画效果和页面布局) 一行代码集成微信悬浮窗 可拖动,大小的视图,可放置在屏幕边缘. 在使用 ...

  6. IOS实现多媒体音频之音乐播放器

    随着智能手机市场越来越活跃,相应的app也变得五彩缤纷,各式各样,让你的app更吸引人多媒体技术不可避免.通过对音频和视频等控制让你的app更加丰富多彩,今天和大家一起研究下基本的音频使用.本文只提供 ...

  7. 简单的HTML5音乐播放器(带歌词滚动)

      // // 0) { this.lrcArr.push(item); } } frag = document.createDocumentFragment(); for(i = 0,len = t ...

  8. jquery音乐播放器(歌词滚动版)

    好久没出来水了!!!忙忙碌碌的找工作~然后中秋节也算过了,祝各位coding们,直接觉醒第七感小宇宙,直接用心就能找到bug-_-// 最后如题这是一篇很正规的coding的文章 大概么比以前的加了个 ...

  9. Android自定义View,高仿QQ音乐歌词滚动控件!

    最近在以QQ音乐为样板做一个手机音乐播放器,源码下篇博文放出.今天我想聊的是这个QQ音乐播放器中歌词显示控件的问题,和小伙伴们一起来探讨怎么实现这个歌词滚动的效果.OK,废话不多说,先来看看效果图: ...

随机推荐

  1. 教女朋友写第一个php

    1 首先 下载xampp 软件.按默认安装好之后 在电脑的右下角的箭头里能发现一个橘色的小图标 双击它 启动阿帕奇和mysql 会变绿 2 打开 C:\xampp\apache 文件夹 找到httpd ...

  2. DOM 节点node

    DOM可以将任何HTML或XML文档描绘成一个有多层节点构成的结构,即在HTML中所有内容都是节点.文档节点是每个文档的根节点,文档节点有一个子节点,称为文档元素.每个文档只能有一个文档元素.在HTM ...

  3. python 网络内容: 初识socket

    一 C\S架构,客户端服务端架构 客户端(client) : 享受服务端提供的服务 服务端(server) : 给客户端提供服务 B\S 浏览器和服务端 B(browser) 二 网络通信的整个流程( ...

  4. 【Django】django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.

    最近学习Django的过程中,在cmd打算使用python manage.py shell来测试数据的时候,当我一导入自己写的model类,就发现报了这个错误django.core.exception ...

  5. java中的throw、throws和try catch浅析

    今天在公司和同事聊天的时候,突然发现自己对java中的throw.throws和try catch的作用理解不够准确,在网上查了查,在此大概梳理一下. throw用于抛出异常,例如 throw new ...

  6. python爬虫 scrapy框架(一)爬取壁纸照片

    此项目仅供学习参考, 不用于任何商业用途 若侵权留言,立刻删除 刚入门爬虫不久,一心想找个网站试试,然后朋友推荐了这个壁纸网站   

  7. eclipse中tomcat可以start启动,无法debug启动的解决

    设置断点,进行程序调试,但是debug启动tomcat,却无法启动,并且会报超时异常. 原因可能是eclipse和tomcat启动时读取文件发生冲突 去掉所有的断点,然后重新debug启动,再设置断点 ...

  8. Less入门及知识点整理

    LESS « 一种动态样式语言 文档链接:http://www.bootcss.com/p/lesscss/ 百科 Less 是一门 CSS 预处理语言,它扩充了 CSS 语言,增加了诸如变量.混合( ...

  9. Linux驱动之异常处理体系结构简析

    异常的概念在单片机中也接触过,它的意思是让CPU可以暂停当前的事情,跳到异常处理程序去执行.以前写单片机裸机程序属于前后台程序,前台指的就是mian函数里的while(1)大循环,后台指的就是产生异常 ...

  10. CentOS_mini下安装docker 之 yum mount

    --->linux 终端输出太多前面看不到的解决办法:shift+page up --->mount命令[-参数] [设备名称] [挂载点] mkdir /mnt/CentOS mount ...