功能概览:
播放/暂停/停止
上一曲/下一曲/点击列表中的歌曲名称播放对应歌曲
显示播放列表/显示正在播放的歌曲名称
循环播放/随机播放
音量/进度条/可拖动进度条控制播放进度/进度时间显示
白天模式/夜间模式
界面效果:
功能介绍:
播放/暂停/停止:
当点击播放按钮,按钮变为选中状态,文字为"暂停播放",再次点击会暂停. 当点击下一曲/上一曲或者选择歌曲列表中的歌名的时候,会自动播放,播放按钮状态变为选中状态.当点击停止按钮,歌曲进度变为00:00.上一曲/下一曲/点击列表中的歌曲名称播放对应歌曲:
点击上一曲/下一曲会播放列表中对应的上一曲/下一曲,歌名会对应显示,点击列表中的歌曲名称播放对应歌曲.显示播放列表/显示正在播放的歌曲名称
循环播放/随机播放:
当选择循环播放,歌曲播放完毕会自动播放列表中对应的下一曲,点击上一曲/下一曲会播放列表中对应的上一曲/下一曲;当选择随机播放,歌曲播放完毕之后或者点击上一曲/下一曲会随机播放列表中的一首歌曲.音量/进度条/可拖动进度条控制播放进度/进度时间显示
白天模式/夜间模式
源代码
storyboard - 随便拖的,没做自动布局 模拟器6s
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface ViewController ()<AVAudioPlayerDelegate,UITableViewDelegate,UITableViewDataSource,AVAudioPlayerDelegate>
//播放器
@property (nonatomic, strong) AVAudioPlayer *player;
//表示进度的slider
@property (weak, nonatomic) IBOutlet UISlider *progressSlider;
//计时器
@property (nonatomic, strong) NSTimer *timer;
//显示时间进度的label
@property (weak, nonatomic) IBOutlet UILabel *progressLabel;
//音乐名称
@property (weak, nonatomic) IBOutlet UILabel *musicNameLabel;
//存储音乐url的数组
@property (nonatomic, strong) NSArray *musicArray;
//音乐的下标
@property (nonatomic, assign) NSInteger index;
//音乐列表的tableView
@property (nonatomic, strong) UITableView *tableView;
//开始按钮
@property (weak, nonatomic) IBOutlet UIButton *startButton;
//循环模式的segControl
@property (weak, nonatomic) IBOutlet UISegmentedControl *repeatModelSegControl;
//夜间模式的segControl
@property (weak, nonatomic) IBOutlet UISegmentedControl *tintModelControl;
@end
@implementation ViewController
//懒加载音乐url数组
- (NSArray *)musicArray {
if (_musicArray == nil) {
// _musicArray = [NSArray array];
NSURL *url0 = [[NSBundle mainBundle] URLForResource:@"好妹妹乐队-你曾是少年.mp3" withExtension:nil];
NSURL *url1 = [[NSBundle mainBundle] URLForResource:@"陈小春 - 扑火.mp3" withExtension:nil];
NSURL *url2 = [[NSBundle mainBundle] URLForResource:@"赵雷-画.mp3" withExtension:nil];
NSURL *url3 = [[NSBundle mainBundle] URLForResource:@"赵雷-家乡.mp3" withExtension:nil];
NSURL *url4 = [[NSBundle mainBundle] URLForResource:@"林峯 - 爱在记忆中找你.mp3" withExtension:nil];
NSURL *url5 = [[NSBundle mainBundle] URLForResource:@"宁夏 - 午餐.mp3" withExtension:nil];
NSURL *url6 = [[NSBundle mainBundle] URLForResource:@"张敬轩-愿望树上.mp3" withExtension:nil];
_musicArray = @[url0,url1,url2,url3,url4,url5,url6];
}
return _musicArray;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.index = 0;
//创建音乐列表的tableView
UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(20, 350, 340, 250) style:UITableViewStylePlain];
self.tableView = tableView;
//设置代理和数据源
self.tableView.delegate = self;
self.tableView.dataSource = self;
//添加
[self.view addSubview:tableView];
[self loadMusic];
//设置子控件们的tintColor
NSArray *array = [self.view subviews];
[array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj setTintColor:[UIColor grayColor]];
}];
}
- (void)loadMusic {
//创建一个错误对象,用来接收错误信息
NSError *error;
//创建播放器对象 传入本地url
self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:self.musicArray[self.index] error:&error];
//设置代理
self.player.delegate = self;
//打印错误信息
if (error) {
NSLog(@"%@",error);
}
//创建一个计时器,用于记录播放进度--在计时器方法里把currentTime赋值给slider的value
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(sliderDisplay) userInfo:nil repeats:YES];
//设置slider的最大值
self.progressSlider.maximumValue = self.player.duration;
//音乐名称
NSURL *url = self.self.musicArray[self.index];
self.musicNameLabel.text = url.lastPathComponent;
}
//控制音量的slider
- (IBAction)volumeSlider:(UISlider *)sender {
self.player.volume = sender.value;
}
//开始播放按钮
- (IBAction)startClick:(UIButton *)sender {
if (!sender.selected) {
//如果player是空的 就读取音乐 否则就是已经在播放 再次点击的时候不能重新读取音乐
if (self.player == nil) {
[self loadMusic];
}
//准备播放, 可不写 为了规范要写.
[self.player prepareToPlay];
//播放
[self.player play];
sender.selected = YES;
} else {
[self.player pause];
sender.selected = NO;
}
}
//暂停 暂停按钮已删除 合并到播放按钮
//- (IBAction)pauseClick:(id)sender {
// [self.player pause];
//}
//停止
- (IBAction)stopClick:(id)sender {
[self.player pause];
self.player.currentTime = 0;
self.startButton.selected = NO;
}
/** 计时器调用的显示slider的方法 */
- (void)sliderDisplay {
//赋值
self.progressSlider.value = self.player.currentTime;
//转换时间格式
NSString *curren = [self timeFormatted:self.player.currentTime];
NSString *all = [self timeFormatted:self.player.duration];
//把时间拼接赋值给显示时间的label
self.progressLabel.text = [NSString stringWithFormat:@"%@/%@",curren,all];
}
/** 拖动进度条 */
- (IBAction)slideProgress:(UISlider *)sender {
//将当前的播放时间设置为slider的value
self.player.currentTime = sender.value;
}
/** 将秒数转换为分秒格式的时间字符串 */
- (NSString *)timeFormatted:(int)totalSeconds
{
//将秒数转换为时间
NSDate *date = [NSDate dateWithTimeIntervalSince1970:totalSeconds];
NSTimeZone *zone = [NSTimeZone systemTimeZone];
NSInteger interval = [zone secondsFromGMTForDate: date];
NSDate *localeDate = [date dateByAddingTimeInterval: interval];
//设置时间格式
NSDateFormatter *dateformmatter = [[NSDateFormatter alloc] init];
dateformmatter.dateFormat = @"mm:ss";
NSString *time = [dateformmatter stringFromDate:localeDate];
return time;
}
//上一曲
- (IBAction)lastMusicClick:(id)sender {
self.startButton.selected = YES;
if (self.repeatModelSegControl.selectedSegmentIndex == 0) { //顺序播放
if (self.index <= 0) {
self.index = self.musicArray.count - 1;
} else {
self.index--;
}
} else { //随机播放
NSInteger index = arc4random() % self.musicArray.count;
self.index = index;
}
[self loadMusic];
[self.player play];
}
//下一曲
- (IBAction)nextMusicClick:(id)sender {
self.startButton.selected = YES;
if (self.repeatModelSegControl.selectedSegmentIndex == 0) { //顺序播放
if (self.index >= self.musicArray.count - 1) {
self.index = 0;
} else {
self.index++;
}
} else { //随机播放
NSInteger index = arc4random() % self.musicArray.count;
self.index = index;
}
[self loadMusic];
[self.player play];
}
#pragma mark - 播放结束调用的方法
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
if (self.repeatModelSegControl.selectedSegmentIndex == 0) { //顺序播放
[self nextMusicClick:nil];
} else { //随机播放
NSInteger index = arc4random() % self.musicArray.count;
self.index = index;
[self loadMusic];
[self.player play];
}
// 音频播放完成时,调用该方法。
// 参数flag:如果音频播放无法解码时,该参数为NO。
//当音频被终端时,该方法不被调用。而会调用audioPlayerBeginInterruption方法
// 和audioPlayerEndInterruption方法
}
//数据源
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.musicArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [[UITableViewCell alloc] init];
NSURL *url = self.musicArray[indexPath.row];
cell.textLabel.text = url.lastPathComponent;
cell.textColor = [UIColor grayColor];
if (self.tintModelControl.selectedSegmentIndex == 0) { //白天模式的颜色
cell.contentView.backgroundColor = [UIColor whiteColor];
} else { //夜间模式的颜色
cell.contentView.backgroundColor = [UIColor darkGrayColor];
}
return cell;
}
//选中cell
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.startButton.selected = YES;
self.index = indexPath.row;
//读取音乐 播放音乐
[self loadMusic];
[self.player play];
}
//夜间模式选择按钮
- (IBAction)tintModelClick:(UISegmentedControl *)sender {
if (sender.selectedSegmentIndex == 0) { //白天模式
self.view.backgroundColor = [UIColor whiteColor];
//在cell方法里设置了cell的相关颜色,所以需要重新加载数据
[self.tableView reloadData];
} else { //夜间模式
self.view.backgroundColor = [UIColor darkGrayColor];
[self.tableView reloadData];
}
}
@end