iOS开发-音乐播放器(复杂版)

那么现在给同学补齐一个还算比较完整功能的音乐播放器,还有待完善!废话不多说,直接上代码!先看示例:

iOS开发-音乐播放器(复杂版).gif
//

//  AppDelegate.h

//  05-音乐播放器

//

//  Created by 周昭 on 2017/3/20.

//  Copyright © 2017年 ZZ. All rights reserved.

//

#import <UIKit/UIKit.h>

typedef void (^remoteBlock)(UIEvent *event);

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

/**

 *  一个回调远程事件的block

 */

@property (nonatomic, copy) remoteBlock removteBlock;

@end

//

//  AppDelegate.m

//  05-音乐播放器

//

//  Created by 周昭 on 2017/3/20.

//  Copyright © 2017年 ZZ. All rights reserved.

//

#import "AppDelegate.h"

#import <AVFoundation/AVFoundation.h>

@interface  AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

 // 设置音频会话类型

 AVAudioSession *session = [AVAudioSession  sharedInstance];

[session setCategory:AVAudioSessionCategoryPlayback  error:nil];

    [session setActive:YES error:nil];

 // 接收远程事件

[application beginReceivingRemoteControlEvents];

 return  YES;

}

/**

 *  锁屏按钮的远程通知

 */

- (void)remoteControlReceivedWithEvent:(UIEvent *)event

{

 if (event.type == UIEventTypeRemoteControl) {

        if (self.removteBlock) {

            self.removteBlock(event);

        }

    }

}

- (void)applicationDidEnterBackground:(UIApplication *)application {

 // 开启后台任务

[application beginBackgroundTaskWithExpirationHandler:nil];

}

@end

//

//  ZZMusic.h

//  05-音乐播放器

//

//  Created by 周昭 on 2017/3/20.

//  Copyright © 2017年 ZZ. All rights reserved.

//

#import <Foundation/Foundation.h>

@interface ZZMusic : NSObject

@property (copy, nonatomic) NSString *name;

@property (copy, nonatomic) NSString *filename;

@property (copy, nonatomic) NSString *singer;

@property (copy, nonatomic) NSString *singerIcon;

@property (copy, nonatomic) NSString *icon;

@property (nonatomic, assign, getter = isPlaying) BOOL playing;

@end

//

//  ZZMusic.m

//  05-音乐播放器

//

//  Created by 周昭 on 2017/3/20.

//  Copyright © 2017年 ZZ. All rights reserved.

//

#import "ZZMusic.h"

@implementation ZZMusic

@end

//

//  UIImage+ZZ.h

//  05-音乐播放器

//

//  Created by 周昭 on 2017/3/20.

//  Copyright © 2017年 ZZ. All rights reserved.

//

#import <UIKit/UIKit.h>

@interface UIImage (ZZ)

+ (instancetype)circleImageWithName:(NSString *)name borderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor;

@end

//

//  UIImage+ZZ.m

//  05-音乐播放器

//

//  Created by 周昭 on 2017/3/20.

//  Copyright © 2017年 ZZ. All rights reserved.

//

#import "UIImage+ZZ.h"

@implementation UIImage (ZZ)

+ (instancetype)circleImageWithName:(NSString *)name borderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor

{

 // 1.加载原图

    UIImage *oldImage = [UIImage imageNamed:name];

 // 2.开启上下文

    CGFloat imageW = oldImage.size.width + 2 * borderWidth;

    CGFloat imageH = oldImage.size.height + 2 * borderWidth;

    CGSize imageSize = CGSizeMake(imageW, imageH);

 UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0);

 // 3.取得当前的上下文

 CGContextRef ctx = UIGraphicsGetCurrentContext();

 // 4.画边框(大圆)

    [borderColor set];

    CGFloat bigRadius = imageW * 0.5; // 大圆半径

    CGFloat centerX = bigRadius; // 圆心

    CGFloat centerY = bigRadius;

    CGContextAddArc(ctx, centerX, centerY, bigRadius, 0, M_PI * 2, 0);

 CGContextFillPath(ctx); // 画圆

 // 5.小圆

    CGFloat smallRadius = bigRadius - borderWidth;

    CGContextAddArc(ctx, centerX, centerY, smallRadius, 0, M_PI * 2, 0);

 // 裁剪(后面画的东西才会受裁剪的影响)

 CGContextClip(ctx);

 // 6.画图

    [oldImage drawInRect:CGRectMake(borderWidth, borderWidth, oldImage.size.width, oldImage.size.height)];

 // 7.取图

 UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

 // 8.结束上下文

 UIGraphicsEndImageContext();

    return newImage;

}

@end

//

//  NSString+ZZ.h

//  05-音乐播放器

//

//  Created by 周昭 on 2017/3/21.

//  Copyright © 2017年 ZZ. All rights reserved.

//

#import <Foundation/Foundation.h>

@interface NSString (ZZ)

/**

 *  返回分与秒的字符串 如:01:60

 */

+ (NSString *)getMinuteSecondWithSecond:(NSTimeInterval)time;

@end

//

//  NSString+ZZ.m

//  05-音乐播放器

//

//  Created by 周昭 on 2017/3/21.

//  Copyright © 2017年 ZZ. All rights reserved.

//

#import "NSString+ZZ.h"

@implementation NSString (ZZ)

+ (NSString *)getMinuteSecondWithSecond:(NSTimeInterval)time {

    int minute = (int)time / 60;

    int second = (int)time % 60;

    if (second > 9) { //2:10

        return [NSString stringWithFormat:@"%d:%d",minute,second];

    }

 //2:09

    return [NSString stringWithFormat:@"%d:0%d",minute,second];

}

@end

//

//  ZZAudioTool.h

//  05-音乐播放器

//

//  Created by 周昭 on 2017/3/20.

//  Copyright © 2017年 ZZ. All rights reserved.

//

#import <Foundation/Foundation.h>

#import <AVFoundation/AVFoundation.h>

@class  ZZMusic;

@interface ZZAudioTool : NSObject

/**

 *  播放器

 */

@property(nonatomic, strong) AVAudioPlayer *player;

/*

 * 音乐播放前的准备工作

 */

- (void)prepareToPlayWithMusic:(ZZMusic *)music;

/*

 * 播放

 */

- (void)play;

/*

 * 暂停

 */

- (void)pause;

/**

 *  创建单例

 */

+ (instancetype)shareInstance;

/**

 *  播放音效

 *

 *  @param filename 音效文件名

 */

+ (void)playSound:(NSString *)filename;

/**

 *  销毁音效

 *

 *  @param filename 音效文件名

 */

+ (void)disposeSound:(NSString *)filename;

/**

 *  播放音乐

 *

 *  @param filename 音乐文件名

 */

+ (AVAudioPlayer *)playMusic:(NSString *)filename;

/**

 *  暂停音乐

 *

 *  @param filename 音乐文件名

 */

+ (void)pauseMusic:(NSString *)filename;

/**

 *  停止音乐

 *

 *  @param filename 音乐文件名

 */

+ (void)stopMusic:(NSString *)filename;

/**

 *  返回当前正在播放的音乐播放器

 */

+ (AVAudioPlayer *)currentPlayingAudioPlayer;

@end

//

//  ZZAudioTool.m

//  05-音乐播放器

//

//  Created by 周昭 on 2017/3/20.

//  Copyright © 2017年 ZZ. All rights reserved.

//

#import "ZZAudioTool.h"

#import "ZZMusic.h"

#import <MediaPlayer/MediaPlayer.h>

@implementation ZZAudioTool

/**

 *  存放所有的音频ID

 *  字典: filename作为key, soundID作为value

 */

static  NSMutableDictionary *_soundIDDict;

/**

 *  存放所有的音乐播放器

 *  字典: filename作为key, audioPlayer作为value

 */

static NSMutableDictionary *_audioPlayerDict;

/**

 *  返回请求单例对象

 */

+ (instancetype)shareInstance

{

    static ZZAudioTool *audioTool;

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        if (audioTool == nil) {

            audioTool = [[ZZAudioTool alloc] init];

        }

    });

    return audioTool;

}

- (void)prepareToPlayWithMusic:(ZZMusic *)music

{

    if (!music.filename) return;

 // 创建播放器

 NSURL *musicURL = [[NSBundle  mainBundle] URLForResource:music.filename  withExtension:nil];

 self.player = [[AVAudioPlayer  alloc] initWithContentsOfURL:musicURL error:nil];

 // 准备

    [self.player  prepareToPlay];

 // 设置锁屏歌曲信息

    [self  setUpLockInfoWithMP3Info:music];

}

- (void)setUpLockInfoWithMP3Info:(ZZMusic *)music

{

    NSLog(@"%s",__func__);

 //锁屏信息设置

 NSMutableDictionary *playingInfo = [NSMutableDictionary  dictionary];

 //1.专辑名称

    playingInfo[MPMediaItemPropertyAlbumTitle] = @"中文十大金曲";

 //2.歌曲

    playingInfo[MPMediaItemPropertyTitle] = music.name;

 //3.歌手名称

    playingInfo[MPMediaItemPropertyTitle] = music.singer;

 //4.专辑图片

    if(music.icon){

        UIImage *artWorkImage = [UIImage imageNamed:music.icon];

        MPMediaItemArtwork *artwork = [[MPMediaItemArtwork alloc] initWithImage:artWorkImage];

        playingInfo[MPMediaItemPropertyArtwork] = artwork;

    }

 //5.锁屏音乐总时间

    playingInfo[MPMediaItemPropertyPlaybackDuration] = @(self.player.duration);

 //设置锁屏时的播放信息

    [MPNowPlayingInfoCenter  defaultCenter].nowPlayingInfo = playingInfo;

}

/*

 * 播放

 */

- (void)play

{

    [self.player play];

}

/*

 * 暂停

 */

- (void)pause

{

    [self.player pause];

}

/**

 *  初始化

 */

+ (void)initialize

{

 _soundIDDict = [NSMutableDictionary  dictionary];

 _audioPlayerDict = [NSMutableDictionary  dictionary];

}

/**

 *  播放音效

 *

 *  @param filename 音效文件名

 */

+ (void)playSound:(NSString *)filename

{

    if (!filename) return;

 // 1.从字典中取出soundID

    SystemSoundID soundID = [_soundIDDict[filename] unsignedLongValue];

    if (!soundID) { // 创建

 // 加载音效文件

 NSURL *url = [[NSBundle  mainBundle] URLForResource:filename withExtension:nil];

        if (!url) return;

 // 创建音效ID

 AudioServicesCreateSystemSoundID((__bridge  CFURLRef)url, &soundID);

        // 放入字典

        _soundIDDict[filename] = @(soundID);

    }

 // 2.播放

 AudioServicesPlaySystemSound(soundID);

}

/**

 *  销毁音效

 *

 *  @param filename 音效文件名

 */

+ (void)disposeSound:(NSString *)filename

{

    if (!filename) return;

    SystemSoundID soundID = [_soundIDDict[filename] unsignedLongValue];

    if (soundID) {

 // 销毁音效ID

 AudioServicesDisposeSystemSoundID(soundID);

 // 从字典中移除

        [_soundIDDict removeObjectForKey:filename];

    }

}

/**

 *  播放音乐

 *

 *  @param filename 音乐文件名

 */

+ (AVAudioPlayer *)playMusic:(NSString *)filename

{

    if (!filename) return nil;

 // 1.从字典中取出audioPlayer

    AVAudioPlayer *audioPlayer = _audioPlayerDict[filename];

    if (!audioPlayer) { // 创建

 // 加载音乐文件

 NSURL *url = [[NSBundle  mainBundle] URLForResource:filename withExtension:nil];

        if (!url) return nil;

 // 创建audioPlayer

        audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];

        // 缓冲

        [audioPlayer prepareToPlay];

 //        audioPlayer.enableRate = YES;

 //        audioPlayer.rate = 10.0;

        // 放入字典

        _audioPlayerDict[filename] = audioPlayer;

    }

 // 2.播放

    if (!audioPlayer.isPlaying) {

        [audioPlayer play];

    }

    return audioPlayer;

}

/**

 *  暂停音乐

 *

 *  @param filename 音乐文件名

 */

+ (void)pauseMusic:(NSString *)filename

{

    if (!filename) return;

 // 1.从字典中取出audioPlayer

    AVAudioPlayer *audioPlayer = _audioPlayerDict[filename];

 // 2.暂停

    if (audioPlayer.isPlaying) {

        [audioPlayer pause];

    }

}

/**

 *  停止音乐

 *

 *  @param filename 音乐文件名

 */

+ (void)stopMusic:(NSString *)filename

{

    if (!filename) return;

 // 1.从字典中取出audioPlayer

    AVAudioPlayer *audioPlayer = _audioPlayerDict[filename];

 // 2.暂停

    if (audioPlayer.isPlaying) {

        [audioPlayer stop];

        // 直接销毁

        [_audioPlayerDict removeObjectForKey:filename];

    }

}

/**

 *  返回当前正在播放的音乐播放器

 */

+ (AVAudioPlayer *)currentPlayingAudioPlayer

{

    for (NSString *filename in _audioPlayerDict) {

        AVAudioPlayer *audioPlayer = _audioPlayerDict[filename];

        if (audioPlayer.isPlaying) {

            return audioPlayer;

        }

    }

 return  nil;

}

@end

//

//  ZZMusicCell.h

//  05-音乐播放器

//

//  Created by 周昭 on 2017/3/20.

//  Copyright © 2017年 ZZ. All rights reserved.

//

#import <UIKit/UIKit.h>

@class  ZZMusic;

@interface ZZMusicCell : UITableViewCell

+ (instancetype)cellWithTableView:(UITableView *)tableView;

@property (nonatomic, strong) ZZMusic *music;

@end

//

//  ZZMusicCell.m

//  05-音乐播放器

//

//  Created by 周昭 on 2017/3/20.

//  Copyright © 2017年 ZZ. All rights reserved.

//

#import "ZZMusicCell.h"

#import "ZZMusic.h"

@interface  ZZMusicCell()

@end

@implementation ZZMusicCell

+ (instancetype)cellWithTableView:(UITableView *)tableView

{

    static NSString *ID = @"music";

 ZZMusicCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    if (cell == nil) {

        cell = [[ZZMusicCell  alloc] initWithStyle:UITableViewCellStyleSubtitle  reuseIdentifier:ID];

    }

    return cell;

}

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier

{

    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {

 self.backgroundColor = [UIColor  clearColor];

 self.selectedBackgroundView = [[UIImageView  alloc] initWithImage:[UIImage  imageNamed:@"backgroundImage"]];

    }

 return  self;

}

- (void)setMusic:(ZZMusic *)music

{

    _music = music;

    self.textLabel.text = music.name;

 self.detailTextLabel.text = music.singer;

 self.imageView.image = [UIImage  imageNamed:music.singerIcon];

}

@end

//

//  ZZPlayerToolBar.h

//  05-音乐播放器

//

//  Created by 周昭 on 2017/3/20.

//  Copyright © 2017年 ZZ. All rights reserved.

//

#import <UIKit/UIKit.h>

typedef enum : NSUInteger {

    ZZPlayerToolBarPreviousButtonType,

    ZZPlayerToolBarNextButtonType,

    ZZPlayerToolBarPlayButtonType,

    ZZPlayerToolBarPauseButtonType,

    ZZPlayerToolBarTypeButtonType

} ZZPlayerToolBarButtonType;

@class  ZZMusic,ZZPlayerToolBar;

@protocol ZZPlayerToolBarDelegate <NSObject>

@optional

- (void)playerToolBar:(ZZPlayerToolBar *)playerToolBar didClickBtnWithType:(ZZPlayerToolBarButtonType)type;

@end

@interface ZZPlayerToolBar : UIView

@property (nonatomic, strong) ZZMusic *music;

@property (nonatomic, assign) ZZPlayerToolBarButtonType type;

@property (nonatomic, weak) id <ZZPlayerToolBarDelegate> delegate;

+ (instancetype)playerToolBar;

@end

//

//  ZZPlayerToolBar.m

//  05-音乐播放器

//

//  Created by 周昭 on 2017/3/20.

//  Copyright © 2017年 ZZ. All rights reserved.

//

#import "ZZPlayerToolBar.h"

#import "ZZMusic.h"

#import "ZZAudioTool.h"

#import "NSString+ZZ.h"

#import "UIImage+ZZ.h"

#import "Colours.h"

@interface  ZZPlayerToolBar()

@property (weak, nonatomic) UIImageView *bgImg;//背景图片

@property (weak, nonatomic) UIImageView *singerIcon;//歌手图片

@property (weak, nonatomic) UIButton *previousBtn;//上一首

@property (weak, nonatomic) UIButton *playBtn;//播放\暂停

@property (weak, nonatomic) UIButton *nextBtn;//下一首

@property (weak, nonatomic) UIButton *typeBtn;//播放模式

@property (weak, nonatomic) UISlider *timeSlider;//滚动条

@property (weak, nonatomic) UILabel *totalTimeLabel;//总时间

@property (weak, nonatomic) UILabel *currentTimeLabel;//当前播放的时间

@property (strong, nonatomic) CADisplayLink *link;//定时器

@property (assign, nonatomic, getter = isDragging) BOOL dragging;//是否正在拖拽

@end

@implementation ZZPlayerToolBar

- (CADisplayLink *)link {

    if (!_link) {

 _link = [CADisplayLink  displayLinkWithTarget:self  selector:@selector(update)];

    }

    return _link;

}

+ (instancetype)playerToolBar

{

    return [[self alloc] init];

}

- (instancetype)initWithFrame:(CGRect)frame

{

    if (self = [super initWithFrame:frame]) {

        [self  setUpSubViews];

        [self.link  addToRunLoop:[NSRunLoop  mainRunLoop] forMode:NSDefaultRunLoopMode];

    }

 return  self;

}

- (instancetype)initWithCoder:(NSCoder *)decoder

{

    if (self = [super initWithCoder:decoder]) {

        [self  setUpSubViews];

        [self.link  addToRunLoop:[NSRunLoop  mainRunLoop] forMode:NSDefaultRunLoopMode];

    }

 return  self;

}

#pragma mark - setUp 初始化

- (void)setUpSubViews

{

 UIImageView *bgImg = [[UIImageView  alloc] init];

    bgImg.image = [UIImage imageNamed:@"play_bar_bg2"];

    [self addSubview:bgImg];

    self.bgImg = bgImg;

    UISlider *timeSlider = [[UISlider alloc] init];

[timeSlider setThumbImage:[UIImage  imageNamed:@"playbar_slider_thumb"] forState:UIControlStateNormal];

[timeSlider addTarget:self  action:@selector(timeSliderChange:) forControlEvents:UIControlEventValueChanged];

    [self addSubview:timeSlider];

    self.timeSlider = timeSlider;

    UILabel *currentTimeLabel = [[UILabel alloc] init];

    currentTimeLabel.font = [UIFont systemFontOfSize:14.0f];

    currentTimeLabel.textColor = [UIColor whiteColor];

    currentTimeLabel.textAlignment = NSTextAlignmentRight;

    currentTimeLabel.text = NSLocalizedString(@"00:00", nil);

    [self addSubview:currentTimeLabel];

    self.currentTimeLabel = currentTimeLabel;

    UILabel *totalTimeLabel = [[UILabel alloc] init];

    totalTimeLabel.font = [UIFont systemFontOfSize:14.0f];

    totalTimeLabel.textColor = [UIColor lightGrayColor];

    totalTimeLabel.textAlignment = NSTextAlignmentLeft;

    totalTimeLabel.text = NSLocalizedString(@"00:00", nil);

    [self addSubview:totalTimeLabel];

    self.totalTimeLabel = totalTimeLabel;

    UIImageView *singerIcon = [[UIImageView alloc] init];

    singerIcon.image = [UIImage imageNamed:@"zxy_icon.jpg"];

    [self addSubview:singerIcon];

    self.singerIcon = singerIcon;

    UIButton *previousBtn = [[UIButton alloc] init];

[previousBtn setImage:[UIImage  imageNamed:@"playbar_prebtn_nomal"] forState:UIControlStateNormal];

[previousBtn setImage:[UIImage  imageNamed:@"playbar_prebtn_click"] forState:UIControlStateHighlighted];

[previousBtn addTarget:self  action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];

    previousBtn.tag = ZZPlayerToolBarPreviousButtonType;

    [self addSubview:previousBtn];

    self.previousBtn = previousBtn;

    UIButton *playBtn = [[UIButton alloc] init];

[playBtn setImage:[UIImage  imageNamed:@"playbar_playbtn_nomal"] forState:UIControlStateNormal];

[playBtn setImage:[UIImage  imageNamed:@"playbar_playbtn_click"] forState:UIControlStateHighlighted];

[playBtn addTarget:self  action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];

    playBtn.tag = ZZPlayerToolBarPlayButtonType;

    [self addSubview:playBtn];

    self.playBtn = playBtn;

    UIButton *nextBtn = [[UIButton alloc] init];

[nextBtn setImage:[UIImage  imageNamed:@"playbar_nextbtn_nomal"] forState:UIControlStateNormal];

[nextBtn setImage:[UIImage  imageNamed:@"playbar_nextbtn_click"] forState:UIControlStateHighlighted];

[nextBtn addTarget:self  action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];

    nextBtn.tag = ZZPlayerToolBarNextButtonType;

    [self addSubview:nextBtn];

    self.nextBtn = nextBtn;

    UIButton *typeBtn = [[UIButton alloc] init];

    typeBtn.layer.borderWidth = 1;

    typeBtn.layer.borderColor = [UIColor  blueColor].CGColor;

[typeBtn addTarget:self  action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];

    typeBtn.tag = ZZPlayerToolBarTypeButtonType;

#warning - 没图先隐藏

    typeBtn.hidden = YES;

    [self addSubview:typeBtn];

    self.typeBtn = typeBtn;

}

- (void)update

{

 // 1.更新进度条

    double currentTime = [ZZAudioTool shareInstance].player.currentTime;

    self.timeSlider.value = currentTime;

 // 2.更新时间

    self.currentTimeLabel.text = [NSString getMinuteSecondWithSecond:currentTime];

}

/**

 *  时间滑动变化

 */

- (void)timeSliderChange:(UISlider *)slider

{

 // 1.播放器进度

    [ZZAudioTool shareInstance].player.currentTime = slider.value;

 // 2.工具条的当前时间

 self.currentTimeLabel.text = [NSString  getMinuteSecondWithSecond:slider.value];

}

/**

 *  点击按钮

 *

 *  @param button 根据按钮类型来判断

 */

- (void)buttonClick:(UIButton *)button

{

    if ([self.delegate respondsToSelector:@selector(playerToolBar:didClickBtnWithType:)]) {

 if (button.tag == ZZPlayerToolBarPlayButtonType) {

            if (self.music.playing) { // 播放

                self.music.playing = NO;

[button setImage:[UIImage  imageNamed:@"playbar_pausebtn_nomal"] forState:UIControlStateNormal];

[button setImage:[UIImage  imageNamed:@"playbar_pausebtn_click"] forState:UIControlStateHighlighted];

                button.tag = ZZPlayerToolBarPauseButtonType;

                [self.delegate  playerToolBar:self  didClickBtnWithType:button.tag];

            }

} else  if (button.tag == ZZPlayerToolBarPauseButtonType) { // 暂停

            self.music.playing = YES;

[button setImage:[UIImage  imageNamed:@"playbar_playbtn_nomal"] forState:UIControlStateNormal];

[button setImage:[UIImage  imageNamed:@"playbar_playbtn_click"] forState:UIControlStateHighlighted];

            button.tag = ZZPlayerToolBarPlayButtonType;

            [self.delegate  playerToolBar:self  didClickBtnWithType:button.tag];

} else  if (button.tag == ZZPlayerToolBarNextButtonType | button.tag == ZZPlayerToolBarPreviousButtonType) {

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

            [self.playBtn  setImage:[UIImage  imageNamed:@"playbar_playbtn_click"] forState:UIControlStateHighlighted];

            [self.delegate  playerToolBar:self  didClickBtnWithType:button.tag];

        } else {

            [self.delegate  playerToolBar:self  didClickBtnWithType:button.tag];

        }

    }

}

/**

 *  拿到真实的尺寸进行子控件的布局

 */

- (void)layoutSubviews

{

#warning - 一定要调用super的方法

    [super  layoutSubviews];

    CGFloat margin = 5;

    self.bgImg.frame = self.frame;

    CGFloat currentTimeLabelX = 10;

    CGFloat currentTimeLabelY = 5;

    CGFloat currentTimeLabelW = 40;

    CGFloat currentTimeLabelH = 30;

    self.currentTimeLabel.frame = CGRectMake(currentTimeLabelX, currentTimeLabelY, currentTimeLabelW, currentTimeLabelH);

    CGFloat timeSliderX = CGRectGetMaxX(self.currentTimeLabel.frame) + margin;

    CGFloat timeSliderY = currentTimeLabelY;

    CGFloat timeSliderW = self.frame.size.width - 2 * (currentTimeLabelW + currentTimeLabelX + margin);

    CGFloat timeSliderH = currentTimeLabelH;

    self.timeSlider.frame = CGRectMake(timeSliderX, timeSliderY, timeSliderW, timeSliderH);

    CGFloat totalTimeLabelX = self.frame.size.width - currentTimeLabelW - currentTimeLabelX;

    CGFloat totalTimeLabelY = currentTimeLabelY;

    CGFloat totalTimeLabelW = currentTimeLabelW;

    CGFloat totalTimeLabelH = currentTimeLabelH;

    self.totalTimeLabel.frame = CGRectMake(totalTimeLabelX, totalTimeLabelY, totalTimeLabelW, totalTimeLabelH);

    CGFloat singerIconX = currentTimeLabelX;

    CGFloat singerIconY = CGRectGetMaxY(self.timeSlider.frame) + margin;

    CGFloat singerIconW = 50;

    CGFloat singerIconH = singerIconW;

    self.singerIcon.frame = CGRectMake(singerIconX, singerIconY, singerIconW, singerIconH);

    CGFloat previousBtnX = CGRectGetMaxX(self.singerIcon.frame) + 25;

    CGFloat previousBtnY = singerIconY;

    CGFloat previousBtnW = 50;

    CGFloat previousBtnH = previousBtnW;

    self.previousBtn.frame = CGRectMake(previousBtnX, previousBtnY, previousBtnW, previousBtnH);

    CGFloat playBtnX = CGRectGetMaxX(self.previousBtn.frame) + 25;

    CGFloat playBtnY = singerIconY - 5;

    CGFloat playBtnW = 60;

    CGFloat playBtnH = playBtnW;

    self.playBtn.frame = CGRectMake(playBtnX, playBtnY, playBtnW, playBtnH);

    CGFloat nextBtnX = CGRectGetMaxX(self.playBtn.frame) + 25;

    CGFloat nextBtnY = singerIconY;

    CGFloat nextBtnW = previousBtnW;

    CGFloat nextBtnH = previousBtnW;

    self.nextBtn.frame = CGRectMake(nextBtnX, nextBtnY, nextBtnW, nextBtnH);

    CGFloat typeBtnX = CGRectGetMaxX(self.nextBtn.frame) + 20;

    CGFloat typeBtnY = singerIconY;

    CGFloat typeBtnW = previousBtnW;

    CGFloat typeBtnH = previousBtnW;

    self.typeBtn.frame = CGRectMake(typeBtnX, typeBtnY, typeBtnW, typeBtnH);

}

#pragma mark - setter 赋值&mvc思想

- (void)setMusic:(ZZMusic *)music

{

    _music = music;

 // 设置歌手图片数据

    [self  setUpSingerIconData];

 // 设置滑动条的数据

    [self  setUpSliderData];

}

/**

 *  设置歌手图片数据

 */

- (void)setUpSingerIconData

{

 // 0.设置圆角

 self.singerIcon.image = [UIImage  circleImageWithName:self.music.singerIcon  borderWidth:2  borderColor:[UIColor  skyBlueColor]];

#warning - 后期再补图片旋转

//    // 1.单位矩阵

//    self.singerIcon.transform = CGAffineTransformIdentity;

}

/**

 *  设置滑动条的数据

 */

- (void)setUpSliderData

{

 // 0.去除当前播放歌曲的总时间

    double duration = [ZZAudioTool shareInstance].player.duration;

 // 1.将时间转换&设置时间属性

 self.totalTimeLabel.text = [NSString  getMinuteSecondWithSecond:duration];

 // 2.设置slider的最大值

    self.timeSlider.maximumValue = duration;

 // 3.重置slider的播放时间

    self.timeSlider.value = 0;

}

- (void)dealloc

{

 //移除定时器

    [self.link  removeFromRunLoop:[NSRunLoop  mainRunLoop] forMode:NSDefaultRunLoopMode];

}

@end

//

//  ZZMusicsController.h

//  05-音乐播放器

//

//  Created by 周昭 on 2017/3/20.

//  Copyright © 2017年 ZZ. All rights reserved.

//

#import <UIKit/UIKit.h>

@interface ZZMusicsController : UIViewController

@end

//

//  ZZMusicsController.m

//  05-音乐播放器

//

//  Created by 周昭 on 2017/3/20.

//  Copyright © 2017年 ZZ. All rights reserved.

//

#import "ZZMusicsController.h"

#import "ZZMusic.h"

#import "ZZMusicCell.h"

#import "ZZAudioTool.h"

#import "MJExtension.h"

#import "ZZPlayerToolBar.h"

#import "NSString+ZZ.h"

#import "AppDelegate.h"

#import <AVFoundation/AVFoundation.h>

@interface  ZZMusicsController ()<UITableViewDelegate,UITableViewDataSource,AVAudioPlayerDelegate,ZZPlayerToolBarDelegate>

@property (nonatomic, strong) NSArray *musics;

@property (nonatomic, strong) AVAudioPlayer *currentPlayingAudioPlayer;

@property (nonatomic, weak) UITableView *tableView;

@property (nonatomic, weak) UIImageView *imgView;

@property (nonatomic, weak) ZZPlayerToolBar *playToolBar;

/**

 *  当前播放的索引

 */

@property (nonatomic, assign) NSInteger musicIndex;

@end

@implementation ZZMusicsController

#pragma mark - 懒加载

- (NSArray *)musics

{

    if (!_musics) {

 self.musics = [ZZMusic  objectArrayWithFilename:@"Musics.plist"];

    }

 return  _musics;

}

- (void)viewDidLoad {

    [super  viewDidLoad];

 // 0.设置标题&背景

    [self  setUpTitle];

 // 1.初始化tableView

    [self  setUpTableView];

 // 2.初始化playerToolBar

    [self  setUpPlayerToolBar];

 // 3.随机播放

    [self  selectIndexPathWithRow:self.musicIndex];

 // 4.接收远程事件

    [self  setUpRemovteEvent];

}

#pragma mark - setUp 初始化

- (void)setUpRemovteEvent

{

    ((AppDelegate *)[UIApplication sharedApplication].delegate).removteBlock = ^(UIEvent *event) {

        switch (event.subtype) {

 case  UIEventSubtypeRemoteControlNextTrack:

                [self playNextMusic];

                break;

 case  UIEventSubtypeRemoteControlPreviousTrack:

                [self playPreviousMusic];

                break;

 case  UIEventSubtypeRemoteControlPause:

                [self pauseCurrentMusic];

                break;

 case  UIEventSubtypeRemoteControlPlay:

                [self playCurrentMusic];

                break;

        }

    };

}

- (void)setUpPlayerToolBar

{

 ZZPlayerToolBar *playToolBar = [ZZPlayerToolBar  playerToolBar];

    playToolBar.frame = CGRectMake(0, self.view.frame.size.height - 95, self.view.frame.size.width, 95);

    playToolBar.delegate = self;

    [self.view addSubview:playToolBar];

    self.playToolBar = playToolBar;

}

- (void)setUpTableView

{

 // 0.创建tableView

    UITableView *tableView = [[UITableView alloc] init];

    tableView.delegate = self;

    tableView.dataSource = self;

    tableView.tableFooterView = [[UIView alloc] init];

 // 1.设置背景

    UIImageView *imgView = [[UIImageView alloc] init];

    imgView.frame = self.view.frame;

    imgView.image = [UIImage imageNamed:@"backgroundImage"];

    tableView.backgroundView = imgView;

    tableView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);

    [self.view addSubview:tableView];

    self.tableView = tableView;

}

- (void)setUpTitle

{

 // 0.设置标题

 self.title = NSLocalizedString(@"音乐播放器", nil);

}

#pragma mark - ZZPlayerToolBarDelegate

- (void)playerToolBar:(ZZPlayerToolBar *)playerToolBar didClickBtnWithType:(ZZPlayerToolBarButtonType)type

{

    switch (type) {

 case  ZZPlayerToolBarPreviousButtonType:

            [self  playPreviousMusic];

            break;

 case  ZZPlayerToolBarNextButtonType:

            [self playNextMusic];

            break;

 case  ZZPlayerToolBarPlayButtonType:

            [self playCurrentMusic];

            break;

 case  ZZPlayerToolBarPauseButtonType:

            [self  pauseCurrentMusic];

            break;

 case  ZZPlayerToolBarTypeButtonType:

            [self playStyleMusic];

            break;

        default:

            break;

    }

}

/**

 *  播放上一首

 */

- (void)playPreviousMusic

{

    if (self.musicIndex == 0) { // 第一首则回到最后一首

        self.musicIndex = self.musics.count - 1;

    } else {

        self.musicIndex--;

    }

    [self  selectIndexPathWithRow:self.musicIndex];

}

/**

 *  播放下一首

 */

- (void)playNextMusic

{

    if (self.musicIndex == self.musics.count - 1) { // 最后一首

        self.musicIndex = 0;

    } else {

        self.musicIndex++;

    }

    [self  selectIndexPathWithRow:self.musicIndex];

}

/**

 *  播放

 */

- (void)playCurrentMusic

{

    [[ZZAudioTool  shareInstance] play];

}

/**

 *  暂停

 */

- (void)pauseCurrentMusic

{

    [[ZZAudioTool  shareInstance] pause];

}

/**

 *  更换播放模式

 */

- (void)playStyleMusic

{

}

- (void)selectIndexPathWithRow:(NSInteger)row

{

 // 0.取得当前选中

    NSIndexPath *selectedPath = [self.tableView indexPathForSelectedRow];

 // 1.主动选中下一行

    NSIndexPath *currentPath = [NSIndexPath indexPathForRow:row inSection:selectedPath.section];

    [self.tableView  selectRowAtIndexPath:currentPath animated:YES  scrollPosition:UITableViewScrollPositionTop];

    [self  tableView:self.tableView  didSelectRowAtIndexPath:currentPath];

 // 2.播放音乐

    [self  playMusic];

}

/**

 *  播放音乐

 */

- (void)playMusic

{

 // 0.取出播放的歌曲

 ZZMusic *music = self.musics[self.musicIndex];

    music.playing = YES;

 // 1.初始化播放器

    [[ZZAudioTool  shareInstance] prepareToPlayWithMusic:music];

 // 2.设置代理

    [ZZAudioTool  shareInstance].player.delegate = self;

 // 3.更改播放工具条数据

 self.playToolBar.music = self.musics[self.musicIndex];

 // 4.播放

    [[ZZAudioTool  shareInstance] play];

}

#pragma mark - Table view data source

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

 return  self.musics.count;

}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

 // 1.创建cell

    ZZMusicCell *cell = [ZZMusicCell cellWithTableView:tableView];

 // 2.设置cell的数据

    cell.music = self.musics[indexPath.row];

    return cell;

}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

    return 70;

}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

 // 0.取出要播放的音乐

    ZZMusic *music = self.musics[indexPath.row];

    if (music.playing == YES) return;

    music.playing = YES;

 // 1.取得索引值

    self.musicIndex = indexPath.row;

 // 2.播放音乐

    [self  playMusic];

}

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath

{

 // 0.停止音乐直接释放

    ZZMusic *music = self.musics[indexPath.row];

    music.playing = NO;

    [ZZAudioTool  stopMusic:music.filename];

}

#pragma mark - AVAudioPlayerDelegate

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag

{

    if (!flag == YES) return;

    [self  playNextMusic];

}

@end
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容