您的位置:首页 > 移动开发 > IOS开发

iOS开发拓展篇—音频处理(音乐播放器4)

2016-06-07 14:02 453 查看
iOS开发拓展篇—音频处理(音乐播放器4)

说明:该文主要介绍音乐播放器实现过程中的一些细节控制。

实现的效果:



一、完整的代码

YYPlayingViewController.m文件

//
//  YYPlayingViewController.m
//  20-音频处理(音乐播放器1)
//
//  Created by apple on 14-8-13.
//  Copyright (c) 2014年 yangyong. All rights reserved.
//

#import "YYPlayingViewController.h"
#import "YYMusicTool.h"
#import "YYMusicModel.h"
#import "YYAudioTool.h"

@interface YYPlayingViewController ()
//进度条
@property (weak, nonatomic) IBOutlet UIView *progressView;
//滑块
@property (weak, nonatomic) IBOutlet UIButton *slider;
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
@property (weak, nonatomic) IBOutlet UILabel *songLabel;
@property (weak, nonatomic) IBOutlet UILabel *singerLabel;
//当前播放的音乐的时长
@property (weak, nonatomic) IBOutlet UILabel *durationLabel;
//正在播放的音乐
@property(nonatomic,strong)YYMusicModel *playingMusic;
//音乐播放器对象
@property(nonatomic,strong)AVAudioPlayer *player;
//定时器
@property(nonatomic,strong)NSTimer *CurrentTimeTimer;
- (IBAction)exit;
- (IBAction)tapProgressBg:(UITapGestureRecognizer *)sender;
- (IBAction)panSlider:(UIPanGestureRecognizer *)sender;

@end

@implementation YYPlayingViewController
#pragma mark-公共方法
-(void)show
{
//1.禁用整个app的点击事件
UIWindow *window=[UIApplication sharedApplication].keyWindow;
window.userInteractionEnabled=NO;

//2.添加播放界面
//设置View的大小为覆盖整个窗口
self.view.frame=window.bounds;
//设置view显示
self.view.hidden=NO;
//把View添加到窗口上
[window addSubview:self.view];

//3.检测是否换了歌曲
if (self.playingMusic!=[YYMusicTool playingMusic]) {
[self RresetPlayingMusic];
}

//4.使用动画让View显示
self.view.y=self.view.height;
[UIView animateWithDuration:0.25 animations:^{
self.view.y=0;
} completion:^(BOOL finished) {

//设置音乐数据
[self starPlayingMusic];
window.userInteractionEnabled=YES;
}];
}

#pragma mark-私有方法
//重置正在播放的音乐
-(void)RresetPlayingMusic
{
//1.重置界面数据
self.iconView.image=[UIImage imageNamed:@"play_cover_pic_bg"];
self.songLabel.text=nil;
self.singerLabel.text=nil;

//2.停止播放
[YYAudioTool stopMusic:self.playingMusic.filename];
//把播放器进行清空
self.player=nil;

//3.停止定时器
[self removeCurrentTime];
}
//开始播放音乐数据
-(void)starPlayingMusic
{
//1.设置界面数据

//如果当前播放的音乐就是传入的音乐,那么就直接返回
if (self.playingMusic==[YYMusicTool playingMusic])
{
//把定时器加进去
[self addCurrentTimeTimer];
return;
}
//存取音乐
self.playingMusic=[YYMusicTool playingMusic];
self.iconView.image=[UIImage imageNamed:self.playingMusic.icon];
self.songLabel.text=self.playingMusic.name;
self.singerLabel.text=self.playingMusic.singer;

//2.开始播放
self.player = [YYAudioTool playMusic:self.playingMusic.filename];

//3.设置时长
//self.player.duration;  播放器正在播放的音乐文件的时间长度
self.durationLabel.text=[self strWithTime:self.player.duration];

//4.添加定时器
[self addCurrentTimeTimer];

}

/**
*把时间长度-->时间字符串
*/
-(NSString *)strWithTime:(NSTimeInterval)time
{
int minute=time / 60;
int second=(int)time % 60;
return [NSString stringWithFormat:@"%d:%d",minute,second];
}

#pragma mark-定时器控制
/**
*  添加一个定时器
*/
-(void)addCurrentTimeTimer
{
//提前先调用一次进度更新,以保证定时器的工作时及时的
[self updateCurrentTime];

//创建一个定时器,每一秒钟调用一次
self.CurrentTimeTimer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateCurrentTime) userInfo:nil repeats:YES];
//把定时器加入到运行时中
[[NSRunLoop mainRunLoop]addTimer:self.CurrentTimeTimer forMode:NSRunLoopCommonModes];
}
/**
*移除一个定时器
*/
-(void)removeCurrentTime
{
[self.CurrentTimeTimer invalidate];

//把定时器清空
self.CurrentTimeTimer=nil;
}

/**
*  更新播放进度
*/
-(void)updateCurrentTime
{
//1.计算进度值
double progress=self.player.currentTime/self.player.duration;

//2.计算滑块的x值
// 滑块的最大的x值
CGFloat sliderMaxX=self.view.width-self.slider.width;
self.slider.x=sliderMaxX*progress;
//设置滑块上的当前播放时间
[self.slider setTitle:[self strWithTime:self.player.currentTime] forState:UIControlStateNormal];

//3.设置进度条的宽度
self.progressView.width=self.slider.center.x;

}

#pragma mark-内部的按钮监听方法
//返回按钮
- (IBAction)exit {

//0.移除定时器
[self  removeCurrentTime];
//1.禁用整个app的点击事件
UIWindow *window=[UIApplication sharedApplication].keyWindow;
window.userInteractionEnabled=NO;

//2.动画隐藏View
[UIView animateWithDuration:0.25 animations:^{
self.view.y=window.height;
} completion:^(BOOL finished) {
window.userInteractionEnabled=YES;
//设置view隐藏能够节省一些性能
self.view.hidden=YES;
}];
}

/**
*点击了进度条
*/
- (IBAction)tapProgressBg:(UITapGestureRecognizer *)sender {
//获取当前单击的点
CGPoint point=[sender locationInView:sender.view];
//切换歌曲的当前播放时间
self.player.currentTime=(point.x/sender.view.width)*self.player.duration;
//更新播放进度
[self updateCurrentTime];
}

- (IBAction)panSlider:(UIPanGestureRecognizer *)sender {

//1.获得挪动的距离
CGPoint t=[sender translationInView:sender.view];
//把挪动清零
[sender setTranslation:CGPointZero inView:sender.view];

//2.控制滑块和进度条的frame
self.slider.x+=t.x;
//设置进度条的宽度
self.progressView.width=self.slider.center.x;

//3.设置时间值
CGFloat sliderMaxX=self.view.width-self.slider.width;
double progress=self.slider.x/sliderMaxX;
//当前的时间值=音乐的时长*当前的进度值
NSTimeInterval time=self.player.duration*progress;
[self .slider setTitle:[self strWithTime:time] forState:UIControlStateNormal];

//4.如果开始拖动,那么就停止定时器
if (sender.state==UIGestureRecognizerStateBegan) {
//停止定时器
[self removeCurrentTime];
}else if(sender.state==UIGestureRecognizerStateEnded)
{
//设置播放器播放的时间
self.player.currentTime=time;
//开启定时器
[self addCurrentTimeTimer];
}
}
@end


二、代码说明(一)

  调整开始播放音乐按钮,让其返回一个音乐播放器,而非BOOL型的。

/**
*播放音乐
*/
+(AVAudioPlayer *)playMusic:(NSString *)filename
{
if (!filename) return nil;//如果没有传入文件名,那么直接返回
//1.取出对应的播放器
AVAudioPlayer *player=[self musicPlayers][filename];

//2.如果播放器没有创建,那么就进行初始化
if (!player) {
//2.1音频文件的URL
NSURL *url=[[NSBundle mainBundle]URLForResource:filename withExtension:nil];
if (!url) return nil;//如果url为空,那么直接返回

//2.2创建播放器
player=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];

//2.3缓冲
if (![player prepareToPlay]) return nil;//如果缓冲失败,那么就直接返回

//2.4存入字典
[self musicPlayers][filename]=player;
}

//3.播放
if (![player isPlaying]) {
//如果当前没处于播放状态,那么就播放
[player play];
}

return player;//正在播放,那么就返回YES
}


三、代码说明(二)

  把时间转换为时间字符串的方法:

/**
*把时间长度-->时间字符串
*/
-(NSString *)strWithTime:(NSTimeInterval)time
{
int minute=time / 60;
int second=(int)time % 60;
return [NSString stringWithFormat:@"%d:%d",minute,second];
}


四、代码说明(三)

  说明:进度控制

  监听当前的播放,使用一个定时器,不断的监听当前是第几秒。

  关于定时器的处理:这里使用了三个方法,分别是添加定时器,移除定时器,和更新播放进度。

注意细节:

(1)移除定时器后,对定时器进行清空处理。

/**
*移除一个定时器
*/
-(void)removeCurrentTime
{
[self.CurrentTimeTimer invalidate];

//把定时器清空
self.CurrentTimeTimer=nil;
}


2)当看不到界面的时候,停止定时器。

(3)在开始播放音乐的方法中进行判断,如果当前播放的音乐和传入的音乐一致,那么添加定时器后直接返回。

(4)重置播放的音乐方法中,停止定时器。

五、代码说明(四)

  说明:点击和拖动进度条的处理

1.点击进度条

  先添加单击的手势识别器。



  往控制器拖线:



涉及的代码:

/**
*点击了进度条
*/
- (IBAction)tapProgressBg:(UITapGestureRecognizer *)sender {
//获取当前单击的点
CGPoint point=[sender locationInView:sender.view];
//切换歌曲的当前播放时间
self.player.currentTime=(point.x/sender.view.width)*self.player.duration;
//更新播放进度
[self updateCurrentTime];
}


2.拖拽进度条

  先添加拖拽手势识别器



往控制器拖线



涉及的代码:

/**
*拖动滑块
*/
- (IBAction)panSlider:(UIPanGestureRecognizer *)sender {

//1.获得挪动的距离
CGPoint t=[sender translationInView:sender.view];
//把挪动清零
[sender setTranslation:CGPointZero inView:sender.view];

//2.控制滑块和进度条的frame
self.slider.x+=t.x;
//设置进度条的宽度
self.progressView.width=self.slider.center.x;

//3.设置时间值
CGFloat sliderMaxX=self.view.width-self.slider.width;
double progress=self.slider.x/sliderMaxX;
//当前的时间值=音乐的时长*当前的进度值
NSTimeInterval time=self.player.duration*progress;
[self .slider setTitle:[self strWithTime:time] forState:UIControlStateNormal];

//4.如果开始拖动,那么就停止定时器
if (sender.state==UIGestureRecognizerStateBegan) {
//停止定时器
[self removeCurrentTime];
}else if(sender.state==UIGestureRecognizerStateEnded)
{
//设置播放器播放的时间
self.player.currentTime=time;
//开启定时器
[self addCurrentTimeTimer];
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: