iOS開發(fā)拓展篇—音頻處理(音樂播放器4)

說明:該文主要介紹音樂播放器實現(xiàn)過程中的一些細節(jié)控制。

實現(xiàn)的效果:

一丈秩、完整的代碼

YYPlayingViewController.m文件

復(fù)制代碼
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 UIView *progressView;
17 //滑塊
18 @property (weak, nonatomic) IBOutlet UIButton *slider;
19 @property (weak, nonatomic) IBOutlet UIImageView *iconView;
20 @property (weak, nonatomic) IBOutlet UILabel *songLabel;
21 @property (weak, nonatomic) IBOutlet UILabel *singerLabel;
22 //當前播放的音樂的時長
23 @property (weak, nonatomic) IBOutlet UILabel *durationLabel;
24 //正在播放的音樂
25 @property(nonatomic,strong)YYMusicModel *playingMusic;
26 //音樂播放器對象
27 @property(nonatomic,strong)AVAudioPlayer *player;
28 //定時器
29 @property(nonatomic,strong)NSTimer *CurrentTimeTimer;
30 - (IBAction)exit;
31 - (IBAction)tapProgressBg:(UITapGestureRecognizer )sender;
32 - (IBAction)panSlider:(UIPanGestureRecognizer )sender;
33
34 @end
35
36 @implementation YYPlayingViewController
37 #pragma mark-公共方法
38 -(void)show
39 {
40 //1.禁用整個app的點擊事件
41 UIWindow window=[UIApplication sharedApplication].keyWindow;
42 window.userInteractionEnabled=NO;
43
44 //2.添加播放界面
45 //設(shè)置View的大小為覆蓋整個窗口
46 self.view.frame=window.bounds;
47 //設(shè)置view顯示
48 self.view.hidden=NO;
49 //把View添加到窗口上
50 [window addSubview:self.view];
51
52 //3.檢測是否換了歌曲
53 if (self.playingMusic!=[YYMusicTool playingMusic]) {
54 [self RresetPlayingMusic];
55 }
56
57 //4.使用動畫讓View顯示
58 self.view.y=self.view.height;
59 [UIView animateWithDuration:0.25 animations:^{
60 self.view.y=0;
61 } completion:^(BOOL finished) {
62
63 //設(shè)置音樂數(shù)據(jù)
64 [self starPlayingMusic];
65 window.userInteractionEnabled=YES;
66 }];
67 }
68
69
70 #pragma mark-私有方法
71 //重置正在播放的音樂
72 -(void)RresetPlayingMusic
73 {
74 //1.重置界面數(shù)據(jù)
75 self.iconView.image=[UIImage imageNamed:@"play_cover_pic_bg"];
76 self.songLabel.text=nil;
77 self.singerLabel.text=nil;
78
79 //2.停止播放
80 [YYAudioTool stopMusic:self.playingMusic.filename];
81 //把播放器進行清空
82 self.player=nil;
83
84 //3.停止定時器
85 [self removeCurrentTime];
86 }
87 //開始播放音樂數(shù)據(jù)
88 -(void)starPlayingMusic
89 {
90 //1.設(shè)置界面數(shù)據(jù)
91
92 //如果當前播放的音樂就是傳入的音樂,那么就直接返回
93 if (self.playingMusic==[YYMusicTool playingMusic])
94 {
95 //把定時器加進去
96 [self addCurrentTimeTimer];
97 return;
98 }
99 //存取音樂
100 self.playingMusic=[YYMusicTool playingMusic];
101 self.iconView.image=[UIImage imageNamed:self.playingMusic.icon];
102 self.songLabel.text=self.playingMusic.name;
103 self.singerLabel.text=self.playingMusic.singer;
104
105 //2.開始播放
106 self.player = [YYAudioTool playMusic:self.playingMusic.filename];
107
108 //3.設(shè)置時長
109 //self.player.duration; 播放器正在播放的音樂文件的時間長度
110 self.durationLabel.text=[self strWithTime:self.player.duration];
111
112 //4.添加定時器
113 [self addCurrentTimeTimer];
114
115 }
116
117 /

118 把時間長度-->時間字符串
119 /
120 -(NSString )strWithTime:(NSTimeInterval)time
121 {
122 int minute=time / 60;
123 int second=(int)time % 60;
124 return [NSString stringWithFormat:@"%d:%d",minute,second];
125 }
126
127 #pragma mark-定時器控制
128 /

129 * 添加一個定時器
130 /
131 -(void)addCurrentTimeTimer
132 {
133 //提前先調(diào)用一次進度更新摄欲,以保證定時器的工作時及時的
134 [self updateCurrentTime];
135
136 //創(chuàng)建一個定時器摸吠,每一秒鐘調(diào)用一次
137 self.CurrentTimeTimer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateCurrentTime) userInfo:nil repeats:YES];
138 //把定時器加入到運行時中
139 [[NSRunLoop mainRunLoop]addTimer:self.CurrentTimeTimer forMode:NSRunLoopCommonModes];
140 }
141 /

142 移除一個定時器
143 /
144 -(void)removeCurrentTime
145 {
146 [self.CurrentTimeTimer invalidate];
147
148 //把定時器清空
149 self.CurrentTimeTimer=nil;
150 }
151
152 /

153 * 更新播放進度
154 /
155 -(void)updateCurrentTime
156 {
157 //1.計算進度值
158 double progress=self.player.currentTime/self.player.duration;
159
160 //2.計算滑塊的x值
161 // 滑塊的最大的x值
162 CGFloat sliderMaxX=self.view.width-self.slider.width;
163 self.slider.x=sliderMaxX
progress;
164 //設(shè)置滑塊上的當前播放時間
165 [self.slider setTitle:[self strWithTime:self.player.currentTime] forState:UIControlStateNormal];
166
167 //3.設(shè)置進度條的寬度
168 self.progressView.width=self.slider.center.x;
169
170 }
171
172 #pragma mark-內(nèi)部的按鈕監(jiān)聽方法
173 //返回按鈕
174 - (IBAction)exit {
175
176 //0.移除定時器
177 [self removeCurrentTime];
178 //1.禁用整個app的點擊事件
179 UIWindow window=[UIApplication sharedApplication].keyWindow;
180 window.userInteractionEnabled=NO;
181
182 //2.動畫隱藏View
183 [UIView animateWithDuration:0.25 animations:^{
184 self.view.y=window.height;
185 } completion:^(BOOL finished) {
186 window.userInteractionEnabled=YES;
187 //設(shè)置view隱藏能夠節(jié)省一些性能
188 self.view.hidden=YES;
189 }];
190 }
191
192 /

193 *點擊了進度條
194 /
195 - (IBAction)tapProgressBg:(UITapGestureRecognizer )sender {
196 //獲取當前單擊的點
197 CGPoint point=[sender locationInView:sender.view];
198 //切換歌曲的當前播放時間
199 self.player.currentTime=(point.x/sender.view.width)
self.player.duration;
200 //更新播放進度
201 [self updateCurrentTime];
202 }
203
204 - (IBAction)panSlider:(UIPanGestureRecognizer )sender {
205
206 //1.獲得挪動的距離
207 CGPoint t=[sender translationInView:sender.view];
208 //把挪動清零
209 [sender setTranslation:CGPointZero inView:sender.view];
210
211 //2.控制滑塊和進度條的frame
212 self.slider.x+=t.x;
213 //設(shè)置進度條的寬度
214 self.progressView.width=self.slider.center.x;
215
216 //3.設(shè)置時間值
217 CGFloat sliderMaxX=self.view.width-self.slider.width;
218 double progress=self.slider.x/sliderMaxX;
219 //當前的時間值=音樂的時長
當前的進度值
220 NSTimeInterval time=self.player.duration
progress;
221 [self .slider setTitle:[self strWithTime:time] forState:UIControlStateNormal];
222
223 //4.如果開始拖動侮叮,那么就停止定時器
224 if (sender.state==UIGestureRecognizerStateBegan) {
225 //停止定時器
226 [self removeCurrentTime];
227 }else if(sender.state==UIGestureRecognizerStateEnded)
228 {
229 //設(shè)置播放器播放的時間
230 self.player.currentTime=time;
231 //開啟定時器
232 [self addCurrentTimeTimer];
233 }
234 }
235 @end
復(fù)制代碼
二喧笔、代碼說明(一)

調(diào)整開始播放音樂按鈕帽驯,讓其返回一個音樂播放器,而非BOOL型的书闸。

復(fù)制代碼
1 /**
2 *播放音樂
3 */
4 +(AVAudioPlayer *)playMusic:(NSString *)filename
5 {
6 if (!filename) return nil;//如果沒有傳入文件名尼变,那么直接返回
7 //1.取出對應(yīng)的播放器
8 AVAudioPlayer *player=[self musicPlayers][filename];
9
10 //2.如果播放器沒有創(chuàng)建,那么就進行初始化
11 if (!player) {
12 //2.1音頻文件的URL
13 NSURL *url=[[NSBundle mainBundle]URLForResource:filename withExtension:nil];
14 if (!url) return nil;//如果url為空浆劲,那么直接返回
15
16 //2.2創(chuàng)建播放器
17 player=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
18
19 //2.3緩沖
20 if (![player prepareToPlay]) return nil;//如果緩沖失敗嫌术,那么就直接返回
21
22 //2.4存入字典
23 [self musicPlayers][filename]=player;
24 }
25
26 //3.播放
27 if (![player isPlaying]) {
28 //如果當前沒處于播放狀態(tài)哀澈,那么就播放
29 [player play];
30 }
31
32 return player;//正在播放,那么就返回YES
33 }
復(fù)制代碼
三度气、代碼說明(二)

把時間轉(zhuǎn)換為時間字符串的方法:

復(fù)制代碼
1 /**
2 *把時間長度-->時間字符串
3 */
4 -(NSString *)strWithTime:(NSTimeInterval)time
5 {
6 int minute=time / 60;
7 int second=(int)time % 60;
8 return [NSString stringWithFormat:@"%d:%d",minute,second];
9 }
復(fù)制代碼
四割按、代碼說明(三)

說明:進度控制

監(jiān)聽當前的播放,使用一個定時器磷籍,不斷的監(jiān)聽當前是第幾秒适荣。

關(guān)于定時器的處理:這里使用了三個方法,分別是添加定時器择示,移除定時器,和更新播放進度晒旅。

注意細節(jié):

(1)移除定時器后栅盲,對定時器進行清空處理。

復(fù)制代碼
1 /**
2 *移除一個定時器
3 */
4 -(void)removeCurrentTime
5 {
6 [self.CurrentTimeTimer invalidate];
7
8 //把定時器清空
9 self.CurrentTimeTimer=nil;
10 }
復(fù)制代碼
(2)當看不到界面的時候废恋,停止定時器谈秫。

(3)在開始播放音樂的方法中進行判斷,如果當前播放的音樂和傳入的音樂一致鱼鼓,那么添加定時器后直接返回拟烫。

(4)重置播放的音樂方法中,停止定時器迄本。

五硕淑、代碼說明(四)

說明:點擊和拖動進度條的處理

1.點擊進度條

先添加單擊的手勢識別器。

往控制器拖線:

涉及的代碼:

復(fù)制代碼
1 /**
2 *點擊了進度條
3 */
4 - (IBAction)tapProgressBg:(UITapGestureRecognizer )sender {
5 //獲取當前單擊的點
6 CGPoint point=[sender locationInView:sender.view];
7 //切換歌曲的當前播放時間
8 self.player.currentTime=(point.x/sender.view.width)
self.player.duration;
9 //更新播放進度
10 [self updateCurrentTime];
11 }
復(fù)制代碼
2.拖拽進度條

先添加拖拽手勢識別器

往控制器拖線

涉及的代碼:

復(fù)制代碼
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 self.slider.x+=t.x;
13 //設(shè)置進度條的寬度
14 self.progressView.width=self.slider.center.x;
15
16 //3.設(shè)置時間值
17 CGFloat sliderMaxX=self.view.width-self.slider.width;
18 double progress=self.slider.x/sliderMaxX;
19 //當前的時間值=音樂的時長
當前的進度值
20 NSTimeInterval time=self.player.duration
progress;
21 [self .slider setTitle:[self strWithTime:time] forState:UIControlStateNormal];
22
23 //4.如果開始拖動嘉赎,那么就停止定時器
24 if (sender.state==UIGestureRecognizerStateBegan) {
25 //停止定時器
26 [self removeCurrentTime];
27 }else if(sender.state==UIGestureRecognizerStateEnded)
28 {
29 //設(shè)置播放器播放的時間
30 self.player.currentTime=time;
31 //開啟定時器
32 [self addCurrentTimeTimer];
33 }
34 }
復(fù)制代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末置媳,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子公条,更是在濱河造成了極大的恐慌拇囊,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件靶橱,死亡現(xiàn)場離奇詭異寥袭,居然都是意外死亡,警方通過查閱死者的電腦和手機关霸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門传黄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人队寇,你說我怎么就攤上這事尝江。” “怎么了英上?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵炭序,是天一觀的道長啤覆。 經(jīng)常有香客問我,道長惭聂,這世上最難降的妖魔是什么窗声? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮辜纲,結(jié)果婚禮上笨觅,老公的妹妹穿的比我還像新娘。我一直安慰自己耕腾,他們只是感情好见剩,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著扫俺,像睡著了一般苍苞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上狼纬,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天羹呵,我揣著相機與錄音,去河邊找鬼疗琉。 笑死冈欢,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的盈简。 我是一名探鬼主播凑耻,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼柠贤!你這毒婦竟也來了拳话?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤种吸,失蹤者是張志新(化名)和其女友劉穎弃衍,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坚俗,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡镜盯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了猖败。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片速缆。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖恩闻,靈堂內(nèi)的尸體忽然破棺而出艺糜,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布破停,位于F島的核電站翅楼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏真慢。R本人自食惡果不足惜毅臊,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望黑界。 院中可真熱鬧管嬉,春花似錦、人聲如沸朗鸠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽烛占。三九已至胎挎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間扰楼,已是汗流浹背呀癣。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工美浦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留弦赖,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓浦辨,卻偏偏與公主長得像蹬竖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子流酬,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容