zoukankan      html  css  js  c++  java
  • iOS开发拓展篇—音频处理(音乐播放器4)

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

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

    实现的效果:

      

    一、完整的代码

    YYPlayingViewController.m文件

    复制代码
      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     //设置View的大小为覆盖整个窗口
     46     self.view.frame=window.bounds;
     47     //设置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         //设置音乐数据
     64         [self starPlayingMusic];
     65         window.userInteractionEnabled=YES;
     66     }];
     67 }
     68 
     69 
     70 #pragma mark-私有方法
     71 //重置正在播放的音乐
     72 -(void)RresetPlayingMusic
     73 {
     74     //1.重置界面数据
     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 //开始播放音乐数据
     88 -(void)starPlayingMusic
     89 {
     90     //1.设置界面数据
     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.设置时长
    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     //提前先调用一次进度更新,以保证定时器的工作时及时的
    134     [self updateCurrentTime];
    135     
    136     //创建一个定时器,每一秒钟调用一次
    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     //设置滑块上的当前播放时间
    165     [self.slider setTitle:[self strWithTime:self.player.currentTime] forState:UIControlStateNormal];
    166     
    167     //3.设置进度条的宽度
    168     self.progressView.width=self.slider.center.x;
    169     
    170 }
    171 
    172 #pragma mark-内部的按钮监听方法
    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         //设置view隐藏能够节省一些性能
    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     //设置进度条的宽度
    214     self.progressView.width=self.slider.center.x;
    215     
    216     //3.设置时间值
    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         //设置播放器播放的时间
    230         self.player.currentTime=time;
    231         //开启定时器
    232         [self addCurrentTimeTimer];
    233     }
    234 }
    235 @end
    复制代码

    二、代码说明(一)

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

    复制代码
     1 /**
     2  *播放音乐
     3  */
     4 +(AVAudioPlayer *)playMusic:(NSString *)filename
     5 {
     6     if (!filename) return nil;//如果没有传入文件名,那么直接返回
     7     //1.取出对应的播放器
     8     AVAudioPlayer *player=[self musicPlayers][filename];
     9     
    10     //2.如果播放器没有创建,那么就进行初始化
    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创建播放器
    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         //如果当前没处于播放状态,那么就播放
    29          [player play];
    30     }
    31 
    32     return player;//正在播放,那么就返回YES
    33 }
    复制代码

    三、代码说明(二)

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

    复制代码
    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 }
    复制代码

    四、代码说明(三)

      说明:进度控制

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

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

    注意细节:

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

    复制代码
     1 /**
     2  *移除一个定时器
     3  */
     4 -(void)removeCurrentTime
     5 {
     6     [self.CurrentTimeTimer invalidate];
     7     
     8     //把定时器清空
     9     self.CurrentTimeTimer=nil;
    10 }
    复制代码

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

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

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

    五、代码说明(四)

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

    1.点击进度条

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

        

      往控制器拖线:

        

    涉及的代码:

    复制代码
     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 }
    复制代码

    2.拖拽进度条

      先添加拖拽手势识别器

      

    往控制器拖线

      

    涉及的代码:

    复制代码
     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     //设置进度条的宽度
    14     self.progressView.width=self.slider.center.x;
    15     
    16     //3.设置时间值
    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         //设置播放器播放的时间
    30         self.player.currentTime=time;
    31         //开启定时器
    32         [self addCurrentTimeTimer];
    33     }
    34 }
    复制代码
  • 相关阅读:
    Codeforces Round #251 (Div. 2) A
    topcoder SRM 623 DIV2 CatAndRat
    topcoder SRM 623 DIV2 CatchTheBeatEasy
    topcoder SRM 622 DIV2 FibonacciDiv2
    topcoder SRM 622 DIV2 BoxesDiv2
    Leetcode Linked List Cycle II
    leetcode Linked List Cycle
    Leetcode Search Insert Position
    关于vim插件
    Codeforces Round #248 (Div. 2) B. Kuriyama Mirai's Stones
  • 原文地址:https://www.cnblogs.com/LiLihongqiang/p/5700104.html
Copyright © 2011-2022 走看看