简易音乐播放器(仿网易云音乐)

1.前言

最近用在学ios的媒体播放,在学习之余想找一些项目进行实践。我们都知道网易云音乐是音乐软件中的良心产品,歌曲推荐功能更是深入人心,可以想象其背后的推荐算法和歌曲分类究竟有多么强大。用AVAudioPlayer写音乐播放器的时候,自然就想到了模仿网易云音乐,虽然写得比较简单,但是在这里还是给大家分享一下。

想直接看代码略过文章的,点这里github地址。

播放器就长下面这个样

整体效果.gif

UI设计确实很丑。(叫程序员来做设计就是这个结果) 最上面的sliderView能够调节播放器的音量;下面的UIProgressViewUILabel用来显示播放器的进度;而下一曲和上一曲的按钮只是为了装饰中间的播放按钮。

这个音乐播放器主要分为三个部分

1.UI
2.AVAudioPlayer
3.旋转动画

  • 因为UI并不是这篇文章的主要内容,所以只介绍2和3部分,UI部分我是直接通过(storyboard)来完成的,并且只适合在4-inch的屏幕上运行。(PS:在上怎样实现页内跳转?markdown中的jump语法好像在中并不是页内跳转。)
  • 我们已经添加好了资源,如"music.mp3"和一些素材图片。

2.AVAudioPlayer

AVAudioPlayer是AVFoundation.framework里面最基本的一个音频播放器的类。它只能播放一个指定路径的音频,特别地方在于它可以控制播放的次数,播放的时间。它还有一个很强大的功能,就是可以很方便的调节左右声道的音量,从而实现很酷的立体声效果。

首先,引入AVFoundation框架,然后初始化播放器,并加载本地的mp3文件

#import 

property (strong, nonatomic) AVAudioPlayer *player;
//获取mp3文件的路径
 NSBundle *bundle = [NSBundle mainBundle];
    NSString * path = [bundle pathForResource:@"music" ofType:@"mp3"];
    NSURL *musicURL = [NSURL fileURLWithPath:path];
    self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:musicURL error:nil];
    //设置初始的声音值
    self.player.volume = 2;
    //设置代理
    self.player.delegate = self;

这样就创建了一个播放器,要控制播放器AVAudioPlayer中提供了三个方法,分别是:

- (BOOL)play;   //开始播放
- (void)pause;  //暂停播放
- (void)stop;   //停止播放

现在只需要一句[self.player play];,你的模拟器就应该有声音了。

为了让播放器更符合您的要求,下面列出了AVAudioPlayer的一些属性

@property(readonly, getter=isPlaying) BOOL playing; //是否正在播放
@property(readonly) NSUInteger numberOfChannels;  //声道数
@property(readonly) NSTimeInterval duration;  //播放的总时间
@property NSTimeInterval currentTime;  //当前播放时间
@property NSInteger numberOfLoops;  //循环播放次数
@property float volume;  //音量大小

3.旋转动画

选择我们的播放器已经设置好了UI和播放器,剩下模仿网易云音乐的封面旋转动画。

在动画方面我们简单地使用动画CABasicAnimation。

CABasicAnimation是layer层提供的基本单一的"keyframe"动画。我们可以使用animationWithKeyPath:方法来创建一个CABasicAnimation,并且将keyPath存储在渲染树中。(类似于cell的Identifier)

代码如下:

/// 封面图片
@property (weak, nonatomic) IBOutlet UIImageView *coverImageView;
//创建一个绕z轴选择的动画
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    //旋转一周
    animation.toValue = @(2*M_PI);
    //循环次数,尽量大
    animation.repeatCount = MAXFLOAT;
    //执行一次动画需要的时间
    animation.duration = 50.0f;
    [self.coverImageView.layer addAnimation:animation forKey:@"rotationAnimation"];
  • 需要注意的是,我们一给self.coverImageView.layer添加动画,这个动画就马上开始执行了。
  • 至于封面图片转一圈的时间如何确定,我是看转动的速度来估计的,觉得50秒这个时间效果比较好。(如果有知道确切时间的朋友,留言告诉我一下哈。ヽ(≧Д≦)ノ)

动画执行的效果应该是这样的,封面一直缓慢旋转:

封面动画.gif

4.其它一些代码

更新播放进度条,我们可以设置一个定时器,每一秒执行一次下面的代码:

/// 播放进度
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
/// 播放进度的文字Label
@property (weak, nonatomic) IBOutlet UILabel *progressLabel;
//获取音频的总时间
NSTimeInterval totalTimer = self.player.duration;
//获取音频的当前时间
NSTimeInterval currentTime = self.player.currentTime;
    
//根据时间比设置进度条的进度
self.progressView.progress = (currentTime/totalTimer);
    
//把秒转换成分钟
//当前时间的秒和分钟
int currentM = currentTime/60;
int currentS = (int)currentTime%60;
    
 //总时间的秒和分钟
int totalM = totalTimer/60;
int totalS = (int)totalTimer%60;
    
//把时间显示在lable上
NSString *timeString = [NSString stringWithFormat:@"%02d:%02d/%02d:%02d",currentM, currentS, totalM, totalS];
self.progressLabel.text = timeString;

暂停动画和继续动画

  • 暂停就是将layer的速度设置为0,将timeOffset设置为暂停时动画进行的时间。
  • 继续动画就是将layer的速度设置为1,获取暂停动画时设置的timeOffset和动画的运行时间,计算并设置动画的beginTime。
  • 暂停动画和继续动画用于用户点击了暂停和开始播放按钮。

暂停动画:

CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0.0;
layer.timeOffset = pausedTime;

继续动画:

CFTimeInterval pausedTime = [layer timeOffset];
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;

5.最后再唠叨几句

这个播放器的内容就只有这么多(当然不只上面的代码,还有一些细节,比如播放按钮图片的更换和播放结束后的处理等等),也有很多不完善的地方。如果有愿意一起改进的朋友,欢迎在github地址上找到我哦。

END

你可能感兴趣的:(简易音乐播放器(仿网易云音乐))