当前位置: 首页 > news >正文

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

 

相关文章:

  • Storm--一个包含存储和计算的大数据实时计算新系统
  • 033_3
  • 得到手机后台中的应用程序
  • SQLCLUSTER sql数据库监测工具
  • 通过Rman方式创建Oracle11g DataGuard物理备库
  • nmon 监控软件
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • Frame - 快速创建高品质的 Web 应用原型
  • [2544]最短路 (两种算法)(HDU)
  • Spring整合Quartz在Linux下定时器被调用两次
  • 8月第3周中国五大顶级域名增5.7万 美国减4.2万
  • 用cubieboard做示波器
  • STL标准容器类简介
  • 如何建设云数据中心
  • 执行计划中常见index访问方式(转)
  • [nginx文档翻译系列] 控制nginx
  • 【399天】跃迁之路——程序员高效学习方法论探索系列(实验阶段156-2018.03.11)...
  • Angular数据绑定机制
  • avalon2.2的VM生成过程
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • ECMAScript入门(七)--Module语法
  • github指令
  • Gradle 5.0 正式版发布
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • Joomla 2.x, 3.x useful code cheatsheet
  • leetcode-27. Remove Element
  • Lsb图片隐写
  • opencv python Meanshift 和 Camshift
  • vue:响应原理
  • 初识 webpack
  • 初识MongoDB分片
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 给初学者:JavaScript 中数组操作注意点
  • 基于MaxCompute打造轻盈的人人车移动端数据平台
  • 计算机在识别图像时“看到”了什么?
  • 区块链分支循环
  • 深度学习中的信息论知识详解
  • 使用API自动生成工具优化前端工作流
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • 学习使用ExpressJS 4.0中的新Router
  • 译有关态射的一切
  • 鱼骨图 - 如何绘制?
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • 06-01 点餐小程序前台界面搭建
  • 2017年360最后一道编程题
  • #WEB前端(HTML属性)
  • ( 用例图)定义了系统的功能需求,它是从系统的外部看系统功能,并不描述系统内部对功能的具体实现
  • (4)事件处理——(7)简单事件(Simple events)
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (数据结构)顺序表的定义
  • (一)RocketMQ初步认识
  • (一)插入排序
  • .axf 转化 .bin文件 的方法
  • .bat批处理(十一):替换字符串中包含百分号%的子串