美文网首页
基于AVPlayer的自定义音频播放器-蔡哲永

基于AVPlayer的自定义音频播放器-蔡哲永

作者: 河南蓝鸥科技有限公司 | 来源:发表于2016-02-28 22:43 被阅读421次

    在PlayMusicViewController对应的.h文件中

    #import<UIKit/UIKit.h>

    @interface PlayMusicViewController : UIViewController

    @property (nonatomic, strong)NSMutableArray *dataSource; //存储所有的音频数据

    @property (nonatomic)NSInteger index; //存储当前需要播放的音频数据的下标

    //声明一个方法创建音乐播放器界面对象

    + (PlayMusicViewController *)shareWithPlayMusicViewController;

    //定义方法完成音频数据的播放

    - (void)playMusic;

    @end

    在PlayMusicViewController对应的.m文件中代码如下:

    #import "PlayMusicViewController.h"

    #import

    #import "JokeModel.h"

    @interface PlayMusicViewController ()

    @property (strong, nonatomic) IBOutlet UIImageView *backgroundImage; //背景图片

    @property (strong, nonatomic) IBOutlet UILabel *titleLabel; //标题

    @property (strong, nonatomic) IBOutlet UIImageView *needle; //播放杆

    @property (strong, nonatomic) IBOutlet UISlider *progress;

    @property (strong, nonatomic) IBOutlet UIButton *playBtn;

    @property (nonatomic)BOOL orBegin; //记录当前播放杆是否处于起始位置

    @property (nonatomic, strong)NSTimer *timer; //存储时间计时器对象

    @property (nonatomic, strong)AVPlayer *player; //存储播放器对象

    @property (nonatomic, strong)AVPlayerItem *playerItem; //存储音频信息

    @end

    @implementation PlayMusicViewController

    + (PlayMusicViewController *)shareWithPlayMusicViewController {

    static PlayMusicViewController *playV = nil;

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

    playV = [[PlayMusicViewController alloc]initWithNibName:@"PlayMusicViewController" bundle:nil];

    });

    return playV;

    }

    //懒加载常见音频播放器对象

    - (AVPlayer *)player {

    if (_player == nil) {

    self.player = [AVPlayer playerWithPlayerItem:nil];

    }

    return _player;

    }

    - (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view from its nib.

    //为背景图片添加高斯模糊效果

    UIVisualEffectView *effectView = [[UIVisualEffectView alloc]initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];

    effectView.frame = self.backgroundImage.frame;

    [self.backgroundImage addSubview:effectView];

    //修改标签的边角

    self.titleLabel.layer.masksToBounds = YES;

    self.titleLabel.layer.cornerRadius = self.titleLabel.frame.size.width / 2;

    JokeModel *joke = self.dataSource[self.index];

    self.titleLabel.text = joke.title;

    //修改播放杆的锚点坐标

    self.needle.layer.anchorPoint = CGPointMake(0.28, 0.18);

    self.orBegin = YES;

    }

    #pragma mark PlayMusic

    //播放音乐

    - (void)playMusic {

    //1:获取对应的音频数据

    JokeModel *joke = self.dataSource[self.index];

    self.titleLabel.text = joke.title;

    //2:创建AVPlayerItem对象

    AVPlayerItem *playItem = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:joke.audio_64_url]];

    //3:替换播放器之前的Item

    [self.player replaceCurrentItemWithPlayerItem:playItem];

    //4:开始播放

    [self.player play];

    //5:监听播放进度

    [self addObserverForProgress];

    //6:监听播放器的状态

    [self addObserverForState];

    }

    //监听播放进度

    - (void)addObserverForProgress {

    //获取当前播放器的音频信息

    AVPlayerItem *playItem = self.player.currentItem;

    //开始监听播放器播放进度的变化

    __weak PlayMusicViewController *playV = self;

    [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 10.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {

    //获取当前播放的进度

    float currentTime = CMTimeGetSeconds(time);

    //获取音频文件的总时间

    float totleTime = CMTimeGetSeconds(playItem.duration);

    //设置进度条的总大小

    playV.progress.maximumValue = totleTime;

    //改变进度条的进度

    [playV.progress setValue:currentTime animated:YES];

    }];

    }

    //KVO监听当前播放器的播放状态

    - (void)addObserverForState {

    //添加监听者

    [self.player.currentItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];

    }

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

    //获取当前的状态

    AVPlayerStatus statu = [change[@"new"] intValue];

    NSLog(@"%ld", (long)statu);

    //如果状态是准备播放执行相应的操作

    if (statu == AVPlayerStatusReadyToPlay) {

    [self.playBtn setImage:[UIImage imageNamed:@"playing_btn_pause_n"] forState:UIControlStateNormal];

    //旋转播放杆

    [self handleNeedleRoation:NO];

    [self.timer invalidate];

    //创建计时器旋转标题

    self.timer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(handleTitleLabelRotation) userInfo:nil repeats:YES];

    }

    }

    //添加播放完成的监听事件

    -(void)addNotification{

    //给AVPlayerItem添加播放完成通知

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startPlayNextMusic) name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];

    }

    //移除观察者

    -(void)removeNotification{

    [[NSNotificationCenter defaultCenter] removeObserver:self];

    }

    #pragma mark Btn Click

    //上一首

    - (IBAction)previousMusic:(id)sender {

    if (self.index > 0) {

    self.index--;

    }else {

    self.index = self.dataSource.count - 1;

    }

    [self stop];

    [self playMusic];

    }

    //下一首

    - (IBAction)nextMusic:(id)sender {

    [self startPlayNextMusic];

    }

    //执行播放下一首操作

    - (void)startPlayNextMusic {

    if (self.index < self.dataSource.count - 1) {

    self.index++;

    }else {

    self.index = 0;

    }

    [self stop];

    [self playMusic];

    }

    //播放按钮

    - (IBAction)playMusic:(id)sender {

    //1:判断播放器的状态

    //播放状态

    if (self.player.rate == 1) {

    [self stop];

    }else {

    [self playing];

    }

    }

    //定义方法将播放界面的控件恢复为未播放的状态

    - (void)stop {

    [self.player pause]; //暂停播放

    [self.playBtn setImage:[UIImage imageNamed:@"playing_btn_play_n"] forState:UIControlStateNormal];//修改按钮显示的图片

    [self.timer invalidate]; //暂停计时器

    [self handleNeedleRoation:YES];

    }

    //定义方法将播放界面设置为播放状态

    - (void)playing {

    [self.player play]; //启动播放器

    [self.playBtn setImage:[UIImage imageNamed:@"playing_btn_pause_n"] forState:UIControlStateNormal];

    [self.timer invalidate];

    self.timer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(handleTitleLabelRotation) userInfo:nil repeats:YES];

    [self handleNeedleRoation:NO];

    }

    #pragma mark Roation

    - (void)handleTitleLabelRotation {

    self.titleLabel.transform = CGAffineTransformRotate(self.titleLabel.transform, M_PI / 50);

    }

    //定义方法实现播放杆的旋转

    - (void)handleNeedleRoation:(BOOL)orPause {

    //播放状态

    __weak PlayMusicViewController *playV = self;

    if (orPause == NO && self.orBegin == YES) {

    [UIView animateWithDuration:.5 animations:^{

    playV.needle.transform = CGAffineTransformRotate(playV.needle.transform, M_PI / 6);

    }];

    self.orBegin = NO;

    }else if(orPause == YES && self.orBegin == NO) {

    //暂停状态

    [UIView animateWithDuration:.5 animations:^{

    playV.needle.transform = CGAffineTransformRotate(playV.needle.transform, -M_PI / 6);

    }];

    self.orBegin = YES;

    }

    }

    - (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

    }

    #pragma mark Change Progress

    - (IBAction)changeProgress:(UISlider *)sender {

    //改变播放器的进度

    [self.player seekToTime:CMTimeMake(sender.value, 1.0)];

    }

    /*

    #pragma mark - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation

    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    // Get the new view controller using [segue destinationViewController].

    // Pass the selected object to the new view controller.

    }

    */

    @end

    效果图:

    参考代码下载链接:http://pan.baidu.com/s/1pJUSzKR

    如果问题,请加QQ850270358,备注写解决问题,和我单独沟通哦。

    相关文章

      网友评论

          本文标题:基于AVPlayer的自定义音频播放器-蔡哲永

          本文链接:https://www.haomeiwen.com/subject/oqkgkttx.html