iOS开发拓展篇—音频处理(音乐播放器5)
iOS开发拓展篇—音频处理(音乐播放器5)
实现效果:
一、半透明滑块的设置
1 /** 2 *拖动滑块 3 */ 4 - (IBAction)panSlider:(UIPanGestureRecognizer *)sender { 5 6 //1.获得挪动的距离 7 CGPoint t=[sender translationInView:sender.view]; 8 //把挪动清零 9 [sender setTranslation:CGPointZero inView:sender.view]; 10 11 //2.控制滑块和进度条的frame 12 CGFloat sliderMaxX=self.view.width-self.slider.width; 13 self.slider.x+=t.x; 14 //控制滑块的frame,不让其越界 15 if(self.slider.x<0) 16 { 17 self.slider.x=0; 18 }else if (self.slider.x>sliderMaxX) 19 { 20 self.slider.x=sliderMaxX; 21 } 22 //设置进度条的宽度 23 self.progressView.width=self.slider.center.x; 24 25 //3.设置时间值 26 double progress=self.slider.x/sliderMaxX; 27 //当前的时间值=音乐的时长*当前的进度值 28 NSTimeInterval time=self.player.duration*progress; 29 [self.slider setTitle:[self strWithTime:time] forState:UIControlStateNormal]; 30 31 //设置拖拽进度的X的值 32 self.currentTimeView.x=self.slider.x; 33 [self.currentTimeView setTitle:self.slider.currentTitle forState:UIControlStateNormal]; 34 35 //4.如果开始拖动,那么就停止定时器 36 if (sender.state==UIGestureRecognizerStateBegan) { 37 //停止定时器 38 [self removeCurrentTime]; 39 40 //设置拖拽进度 41 //显示 42 self.currentTimeView.hidden=NO; 43 self.currentTimeView.y=self.currentTimeView.superview.height-5-self.currentTimeView.height; 44 45 }else if(sender.state==UIGestureRecognizerStateEnded) 46 { 47 //隐藏 48 self.currentTimeView.hidden=YES; 49 //设置播放器播放的时间 50 self.player.currentTime=time; 51 #warning 如果正在播放,才需要添加定时器 52 // if (self.player.isPlaying) { 53 //开启定时器 54 [self addCurrentTimeTimer]; 55 // } 56 } 57 }
裁剪圆角的细节处理:
二、播放或暂停、上一首、下一首的实现
1 //上一首 2 - (IBAction)previous { 3 //1.在开始播放之前,禁用一切的app点击事件 4 UIWindow *window=[[UIApplication sharedApplication].windows lastObject]; 5 window.userInteractionEnabled=NO; 6 7 //2.重置当前歌曲 8 [self resetPlayingMusic]; 9 10 //3.获得上一首歌曲 11 [YYMusicTool setPlayingMusic:[YYMusicTool previousMusic]]; 12 13 //4.播放上一首歌曲 14 [self starPlayingMusic]; 15 16 //5.回复window的点击为可用 17 window.userInteractionEnabled=YES; 18 } 19 //下一首 20 - (IBAction)next { 21 //1.在开始播放之前,禁用一切的app点击事件 22 UIWindow *window=[[UIApplication sharedApplication].windows lastObject]; 23 window.userInteractionEnabled=NO; 24 25 //2.重置当前歌曲 26 [self resetPlayingMusic]; 27 28 //3.获得下一首歌曲 29 [YYMusicTool setPlayingMusic:[YYMusicTool nextMusic]]; 30 31 //4.播放下一首歌曲 32 [self starPlayingMusic]; 33 34 //5.回复window的点击为可用 35 window.userInteractionEnabled=YES; 36 } 37 38 //继续或暂停播放 39 - (IBAction)playOrPause { 40 if (self.playOrPauseButton.isSelected) {//暂停 41 self.playOrPauseButton.selected=NO; 42 //暂停播放 43 [YYAudioTool pauseMusic:self.playingMusic.filename]; 44 //停掉定时器 45 [self removeCurrentTime]; 46 }else 47 { 48 self.playOrPauseButton.selected=YES; 49 //继续播放 50 [YYAudioTool playMusic:self.playingMusic.filename]; 51 //开启定时器 52 [self addCurrentTimeTimer]; 53 } 54 }
说明:播放和暂停按钮的图片设置在两种状态下并不一样,设置播放按钮的状态
三、对存在的bug进行改进
拖拽还存在问题(定时器的问题)
更好的方法时在添加定时器的地方进行更细的控制:
1 /** 2 * 添加一个定时器 3 */ 4 -(void)addCurrentTimeTimer 5 { 6 //如果当前没有在播放,那么就直接返回 7 if (self.player.isPlaying==NO) return; 8 9 //在添加一个定时器之前,先把以前的定时器移除 10 [self removeCurrentTime]; 11 12 //提前先调用一次进度更新,以保证定时器的工作时及时的 13 [self updateCurrentTime]; 14 15 //创建一个定时器,每一秒钟调用一次 16 self.CurrentTimeTimer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateCurrentTime) userInfo:nil repeats:YES]; 17 //把定时器加入到运行时中 18 [[NSRunLoop mainRunLoop]addTimer:self.CurrentTimeTimer forMode:NSRunLoopCommonModes]; 19 }
四、补充
完整的代码如下:
1 // 2 // YYPlayingViewController.m 3 // 20-音频处理(音乐播放器1) 4 // 5 // Created by apple on 14-8-13. 6 // Copyright (c) 2014年 yangyong. All rights reserved. 7 // 8 9 #import "YYPlayingViewController.h" 10 #import "YYMusicTool.h" 11 #import "YYMusicModel.h" 12 #import "YYAudioTool.h" 13 14 @interface YYPlayingViewController () 15 //显示拖拽进度 16 @property (weak, nonatomic) IBOutlet UIButton *currentTimeView; 17 //进度条 18 @property (weak, nonatomic) IBOutlet UIView *progressView; 19 //滑块 20 @property (weak, nonatomic) IBOutlet UIButton *slider; 21 @property (weak, nonatomic) IBOutlet UIImageView *iconView; 22 @property (weak, nonatomic) IBOutlet UILabel *songLabel; 23 @property (weak, nonatomic) IBOutlet UILabel *singerLabel; 24 //当前播放的音乐的时长 25 @property (weak, nonatomic) IBOutlet UILabel *durationLabel; 26 //正在播放的音乐 27 @property(nonatomic,strong)YYMusicModel *playingMusic; 28 //音乐播放器对象 29 @property(nonatomic,strong)AVAudioPlayer *player; 30 //定时器 31 @property(nonatomic,strong)NSTimer *CurrentTimeTimer; 32 - (IBAction)exit; 33 - (IBAction)tapProgressBg:(UITapGestureRecognizer *)sender; 34 - (IBAction)panSlider:(UIPanGestureRecognizer *)sender; 35 - (IBAction)previous; 36 - (IBAction)playOrPause; 37 - (IBAction)next; 38 @property (weak, nonatomic) IBOutlet UIButton *playOrPauseButton; 39 40 @end 41 42 @implementation YYPlayingViewController 43 44 -(void)viewDidLoad 45 { 46 [super viewDidLoad]; 47 48 //裁剪圆角 49 self.currentTimeView.layer.cornerRadius=8; 50 51 } 52 #pragma mark-公共方法 53 -(void)show 54 { 55 //1.禁用整个app的点击事件 56 UIWindow *window=[UIApplication sharedApplication].keyWindow; 57 window.userInteractionEnabled=NO; 58 59 //2.添加播放界面 60 //设置View的大小为覆盖整个窗口 61 self.view.frame=window.bounds; 62 //设置view显示 63 self.view.hidden=NO; 64 //把View添加到窗口上 65 [window addSubview:self.view]; 66 67 //3.检测是否换了歌曲 68 if (self.playingMusic!=[YYMusicTool playingMusic]) { 69 [self resetPlayingMusic]; 70 } 71 72 //4.使用动画让View显示 73 self.view.y=self.view.height; 74 [UIView animateWithDuration:0.25 animations:^{ 75 self.view.y=0; 76 } completion:^(BOOL finished) { 77 78 //设置音乐数据 79 [self starPlayingMusic]; 80 window.userInteractionEnabled=YES; 81 }]; 82 } 83 84 85 #pragma mark-私有方法 86 //重置正在播放的音乐 87 -(void)resetPlayingMusic 88 { 89 //1.重置界面数据 90 self.iconView.image=[UIImage imageNamed:@"play_cover_pic_bg"]; 91 self.songLabel.text=nil; 92 self.singerLabel.text=nil; 93 94 //2.停止播放 95 [YYAudioTool stopMusic:self.playingMusic.filename]; 96 //把播放器进行清空 97 self.player=nil; 98 99 //3.停止定时器 100 [self removeCurrentTime]; 101 102 //4.设置音乐播放按钮的状态 103 self.playOrPauseButton.selected=NO; 104 } 105 //开始播放音乐数据 106 -(void)starPlayingMusic 107 { 108 //1.设置界面数据 109 110 //如果当前播放的音乐就是传入的音乐,那么就直接返回 111 if (self.playingMusic==[YYMusicTool playingMusic]) 112 { 113 //把定时器加进去 114 [self addCurrentTimeTimer]; 115 return; 116 } 117 //存取音乐 118 self.playingMusic=[YYMusicTool playingMusic]; 119 self.iconView.image=[UIImage imageNamed:self.playingMusic.icon]; 120 self.songLabel.text=self.playingMusic.name; 121 self.singerLabel.text=self.playingMusic.singer; 122 123 //2.开始播放 124 self.player = [YYAudioTool playMusic:self.playingMusic.filename]; 125 126 //3.设置时长 127 //self.player.duration; 播放器正在播放的音乐文件的时间长度 128 self.durationLabel.text=[self strWithTime:self.player.duration]; 129 130 //4.添加定时器 131 [self addCurrentTimeTimer]; 132 133 //5.设置音乐播放按钮的状态 134 self.playOrPauseButton.selected=YES; 135 } 136 137 /** 138 *把时间长度-->时间字符串 139 */ 140 -(NSString *)strWithTime:(NSTimeInterval)time 141 { 142 int minute=time / 60; 143 int second=(int)time % 60; 144 return [NSString stringWithFormat:@"%d:%d",minute,second]; 145 } 146 147 #pragma mark-定时器控制 148 /** 149 * 添加一个定时器 150 */ 151 -(void)addCurrentTimeTimer 152 { 153 //如果当前没有在播放,那么就直接返回 154 if (self.player.isPlaying==NO) return; 155 156 //在添加一个定时器之前,先把以前的定时器移除 157 [self removeCurrentTime]; 158 159 //提前先调用一次进度更新,以保证定时器的工作时及时的 160 [self updateCurrentTime]; 161 162 //创建一个定时器,每一秒钟调用一次 163 self.CurrentTimeTimer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateCurrentTime) userInfo:nil repeats:YES]; 164 //把定时器加入到运行时中 165 [[NSRunLoop mainRunLoop]addTimer:self.CurrentTimeTimer forMode:NSRunLoopCommonModes]; 166 } 167 /** 168 *移除一个定时器 169 */ 170 -(void)removeCurrentTime 171 { 172 [self.CurrentTimeTimer invalidate]; 173 174 //把定时器清空 175 self.CurrentTimeTimer=nil; 176 } 177 178 /** 179 * 更新播放进度 180 */ 181 -(void)updateCurrentTime 182 { 183 //1.计算进度值 184 double progress=self.player.currentTime/self.player.duration; 185 186 //2.计算滑块的x值 187 // 滑块的最大的x值 188 CGFloat sliderMaxX=self.view.width-self.slider.width; 189 self.slider.x=sliderMaxX*progress; 190 //设置滑块上的当前播放时间 191 [self.slider setTitle:[self strWithTime:self.player.currentTime] forState:UIControlStateNormal]; 192 193 //3.设置进度条的宽度 194 self.progressView.width=self.slider.center.x; 195 196 } 197 198 #pragma mark-内部的按钮监听方法 199 //返回按钮 200 - (IBAction)exit { 201 202 //0.移除定时器 203 [self removeCurrentTime]; 204 //1.禁用整个app的点击事件 205 UIWindow *window=[UIApplication sharedApplication].keyWindow; 206 window.userInteractionEnabled=NO; 207 208 //2.动画隐藏View 209 [UIView animateWithDuration:0.25 animations:^{ 210 self.view.y=window.height; 211 } completion:^(BOOL finished) { 212 window.userInteractionEnabled=YES; 213 //设置view隐藏能够节省一些性能 214 self.view.hidden=YES; 215 }]; 216 } 217 218 /** 219 *点击了进度条 220 */ 221 - (IBAction)tapProgressBg:(UITapGestureRecognizer *)sender { 222 //获取当前单击的点 223 CGPoint point=[sender locationInView:sender.view]; 224 //切换歌曲的当前播放时间 225 self.player.currentTime=(point.x/sender.view.width)*self.player.duration; 226 //更新播放进度 227 [self updateCurrentTime]; 228 } 229 /** 230 *拖动滑块 231 */ 232 - (IBAction)panSlider:(UIPanGestureRecognizer *)sender { 233 234 //1.获得挪动的距离 235 CGPoint t=[sender translationInView:sender.view]; 236 //把挪动清零 237 [sender setTranslation:CGPointZero inView:sender.view]; 238 239 //2.控制滑块和进度条的frame 240 CGFloat sliderMaxX=self.view.width-self.slider.width; 241 self.slider.x+=t.x; 242 //控制滑块的frame,不让其越界 243 if(self.slider.x<0) 244 { 245 self.slider.x=0; 246 }else if (self.slider.x>sliderMaxX) 247 { 248 self.slider.x=sliderMaxX; 249 } 250 //设置进度条的宽度 251 self.progressView.width=self.slider.center.x; 252 253 //3.设置时间值 254 double progress=self.slider.x/sliderMaxX; 255 //当前的时间值=音乐的时长*当前的进度值 256 NSTimeInterval time=self.player.duration*progress; 257 [self.slider setTitle:[self strWithTime:time] forState:UIControlStateNormal]; 258 259 //设置拖拽进度的X的值 260 self.currentTimeView.x=self.slider.x; 261 [self.currentTimeView setTitle:self.slider.currentTitle forState:UIControlStateNormal]; 262 263 //4.如果开始拖动,那么就停止定时器 264 if (sender.state==UIGestureRecognizerStateBegan) { 265 //停止定时器 266 [self removeCurrentTime]; 267 268 //设置拖拽进度 269 //显示 270 self.currentTimeView.hidden=NO; 271 self.currentTimeView.y=self.currentTimeView.superview.height-5-self.currentTimeView.height; 272 273 }else if(sender.state==UIGestureRecognizerStateEnded) 274 { 275 //隐藏 276 self.currentTimeView.hidden=YES; 277 //设置播放器播放的时间 278 self.player.currentTime=time; 279 #warning 如果正在播放,才需要添加定时器 280 // if (self.player.isPlaying) { 281 //开启定时器 282 [self addCurrentTimeTimer]; 283 // } 284 } 285 } 286 287 //上一首 288 - (IBAction)previous { 289 //1.在开始播放之前,禁用一切的app点击事件 290 UIWindow *window=[[UIApplication sharedApplication].windows lastObject]; 291 window.userInteractionEnabled=NO; 292 293 //2.重置当前歌曲 294 [self resetPlayingMusic]; 295 296 //3.获得上一首歌曲 297 [YYMusicTool setPlayingMusic:[YYMusicTool previousMusic]]; 298 299 //4.播放上一首歌曲 300 [self starPlayingMusic]; 301 302 //5.回复window的点击为可用 303 window.userInteractionEnabled=YES; 304 } 305 //下一首 306 - (IBAction)next { 307 //1.在开始播放之前,禁用一切的app点击事件 308 UIWindow *window=[[UIApplication sharedApplication].windows lastObject]; 309 window.userInteractionEnabled=NO; 310 311 //2.重置当前歌曲 312 [self resetPlayingMusic]; 313 314 //3.获得下一首歌曲 315 [YYMusicTool setPlayingMusic:[YYMusicTool nextMusic]]; 316 317 //4.播放下一首歌曲 318 [self starPlayingMusic]; 319 320 //5.回复window的点击为可用 321 window.userInteractionEnabled=YES; 322 } 323 //继续或暂停播放 324 - (IBAction)playOrPause { 325 if (self.playOrPauseButton.isSelected) {//暂停 326 self.playOrPauseButton.selected=NO; 327 //暂停播放 328 [YYAudioTool pauseMusic:self.playingMusic.filename]; 329 //停掉定时器 330 [self removeCurrentTime]; 331 }else 332 { 333 self.playOrPauseButton.selected=YES; 334 //继续播放 335 [YYAudioTool playMusic:self.playingMusic.filename]; 336 //开启定时器 337 [self addCurrentTimeTimer]; 338 } 339 } 340 341 342 @end