声明:(部分图片来自网络,如果侵犯了您的权益请联系我,会尽快删除!)
又是音乐播放器,不过这次和上次不一样了,准确说这次更像播放器了,初学者不建议看这个,可以先看前面一个音乐播放器(1),当然 我没加1,写了这个,就把前面的默认当1吧
先上图:
接下来源码:(一样:大量的三元式,多看看就习惯了,主要是习惯一行能干的事绝不用两行);
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 // 2 // ViewController.m 3 // C_MusicPlayer 4 // 5 // Created by Ibokan on 15/8/22. 6 // Copyright (c) 2015年 Crazy凡. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 #import <AVFoundation/AVFoundation.h> 11 #import "LyricsAnalysis.h" 12 13 @interface ViewController () <AVAudioPlayerDelegate> 14 @property (nonatomic,strong)UIImageView *imageview;//bgimg 15 @property (nonatomic,strong)UISlider *slider;//播放进度条 16 @property (nonatomic,strong)UILabel *tlableall;//音乐总时长 17 @property (nonatomic,strong)UILabel *tlablecur;//音乐当前播放时长 18 @property (nonatomic,strong)UILabel *labellrc;//歌词显示label 19 20 @property (nonatomic,strong)UIButton *buttonPlayandPause; 21 @property (nonatomic,strong)UIButton *buttonPrevious; 22 @property (nonatomic,strong)UIButton *buttonNext; 23 @property (nonatomic,strong)AVAudioPlayer *player; 24 @property (nonatomic,strong)LyricsAnalysis *lrc; 25 @property (nonatomic,strong)UIImageView *musicImg; 26 @property (nonatomic,strong)NSTimer *timer;//计时器 27 @property (nonatomic,strong)NSMutableArray *musicListArray;//歌曲列表 28 29 30 @property int indexLrc;//歌词播放指向 31 @property int indexMusicList;//歌曲播放指向 32 33 //@property (nonatomic,strong)UIScrollView * scrollview; 34 @end 35 36 @implementation ViewController 37 38 - (NSArray *)musicListArray//初始化歌曲列表 : 懒加载 39 { 40 if(!_musicListArray) 41 { 42 _musicListArray = [NSMutableArray arrayWithArray:[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"Music.plist" ofType:nil]]]; 43 for(NSDictionary *temp in _musicListArray)//屏蔽无效路径 44 { 45 [[NSBundle mainBundle]pathForResource:[temp valueForKey:@"music"] ofType:nil] ? nil:[_musicListArray removeObject:temp]; 46 } 47 } 48 return _musicListArray; 49 } 50 51 - (void)viewDidLoad { 52 [super viewDidLoad]; 53 // Do any additional setup after loading the view, typically from a nib. 54 55 self.indexLrc = 0; 56 self.indexMusicList = 0; 57 58 self.musicImg = [[UIImageView alloc]initWithFrame:CGRectMake(45, 54, 231, 231)];//初始化歌曲图片 59 self.musicImg.backgroundColor = [UIColor groupTableViewBackgroundColor]; 60 self.musicImg.contentMode = UIViewContentModeScaleAspectFill; 61 [self.view addSubview:self.musicImg]; 62 63 self.imageview = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];//初始化背景 64 [self.imageview setImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"bgimg.png" ofType:nil]]]; 65 self.imageview.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0]; 66 self.imageview.contentMode = UIViewContentModeScaleAspectFill; 67 self.imageview.userInteractionEnabled = true; 68 [self.view addSubview:self.imageview]; 69 70 self.slider = [[UISlider alloc]initWithFrame:CGRectMake(20, 340, 280, 10)];//初始化进度条 71 self.slider.value = 0.0; 72 [self.view addSubview:self.slider]; 73 [self.slider addTarget:self action:@selector(updateValue) forControlEvents:UIControlEventValueChanged]; 74 75 self.labellrc = [[UILabel alloc]initWithFrame:CGRectMake(0, 300, 320, 30)];//初始化歌词显示label 76 self.labellrc.textColor = [UIColor whiteColor]; 77 self.labellrc.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.2]; 78 self.labellrc.textAlignment = NSTextAlignmentCenter; 79 [self.view addSubview:self.labellrc]; 80 81 self.tlablecur = [[UILabel alloc]initWithFrame:CGRectMake(20, 360, 60, 30)];//初始化当前播放时间显示label 82 self.tlablecur.textColor = [UIColor whiteColor]; 83 self.tlablecur.text = @"00:00"; 84 self.tlablecur.textAlignment = NSTextAlignmentCenter; 85 [self.view addSubview:self.tlablecur]; 86 87 self.tlableall = [[UILabel alloc]initWithFrame:CGRectMake(240, 360, 60, 30)];//初始化音乐总时间显示label 88 self.tlableall.textColor = [UIColor whiteColor]; 89 self.tlableall.textAlignment = NSTextAlignmentCenter; 90 [self.view addSubview:self.tlableall]; 91 92 self.buttonPlayandPause = [[UIButton alloc]initWithFrame:CGRectMake(130, 400,60, 60)];//初始化并插入开始and暂停按钮 93 [self.view addSubview:self.buttonPlayandPause]; 94 [self.buttonPlayandPause setBackgroundImage:[UIImage imageNamed:@"start.png"] forState:UIControlStateNormal]; 95 [self.buttonPlayandPause addTarget:self action:@selector(startandpause) forControlEvents:UIControlEventTouchUpInside]; 96 97 self.buttonPrevious = [[UIButton alloc]initWithFrame:CGRectMake(30, 400, 60, 60)];//初始化并插入上一曲按钮 98 [self.view addSubview:self.buttonPrevious]; 99 [self.buttonPrevious setBackgroundImage:[UIImage imageNamed:@"previous.png"] forState:UIControlStateNormal]; 100 [self.buttonPrevious addTarget:self action:@selector(previous) forControlEvents:UIControlEventTouchUpInside]; 101 102 self.buttonNext = [[UIButton alloc]initWithFrame:CGRectMake(230, 400, 60, 60)];//初始化并插入下一曲按钮 103 [self.view addSubview:self.buttonNext]; 104 [self.buttonNext setBackgroundImage:[UIImage imageNamed:@"next.png"] forState:UIControlStateNormal]; 105 [self.buttonNext addTarget:self action:@selector(next) forControlEvents:UIControlEventTouchUpInside]; 106 107 [self addSource];//歌词 歌曲 图片 初始化 108 } 109 - (void)startandpause//设置按钮选项 110 { 111 if([self.player isPlaying]) 112 { 113 [self.timer invalidate]; 114 [self.player pause]; 115 [self.buttonPlayandPause setBackgroundImage:[UIImage imageNamed:@"start.png"] forState:UIControlStateNormal]; 116 } 117 else 118 { 119 [self.player play]; 120 [self.buttonPlayandPause setBackgroundImage:[UIImage imageNamed:@"pause.png"] forState:UIControlStateNormal]; 121 self.timer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(timeadd) userInfo:nil repeats:YES]; 122 self.timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(rotate) userInfo:nil repeats:YES]; 123 } 124 } 125 - (void)playerclear//停止 管理所有的清零事件 126 { 127 self.indexLrc = 0;//歌词指示变0 128 [self.player stop];//播放器停止 129 self.player.currentTime = 0;//当前播放时间停止 130 [self.timer invalidate];//timer 停止 131 self.slider.value = 0;//进度条清零 132 self.tlablecur.text = @"00:00"; 133 self.labellrc.text = [NSString stringWithFormat:@"%@ : %@",self.lrc.ar,self.lrc.ti]; //歌词显示成标题+作者 134 } 135 - (void)addSource//更改歌曲资源 136 { 137 self.player= [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath: [[NSBundle mainBundle]pathForResource:[[self.musicListArray objectAtIndex:self.indexMusicList]valueForKey:@"music"] ofType:nil]]error:nil];//歌曲初始化 138 if(self.player == nil) //防止加载不到音乐文件 139 { 140 [self next] ; 141 return; 142 } 143 self.player.delegate = self;//设置委托回调 144 self.lrc = [[LyricsAnalysis alloc]initWithFileName:[[self.musicListArray objectAtIndex:self.indexMusicList]valueForKey:@"lyrics"] ofType:nil];//歌词初始化 145 NSString *imgUrlTemp = [[NSBundle mainBundle]pathForResource:[[self.musicListArray objectAtIndex:self.indexMusicList]valueForKey:@"picture"]ofType:nil];//检查图片路径 146 [self.musicImg setImage:[UIImage imageWithContentsOfFile:(imgUrlTemp ? imgUrlTemp : [[NSBundle mainBundle]pathForResource:@"noImg.png" ofType:nil])]];//设置图片 147 NSDateFormatter *formatter = [[NSDateFormatter alloc]init];//设置总时间 148 [formatter setDateFormat:@"mm:ss"]; 149 self.tlableall.text = [formatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:self.player.duration]]; 150 self.labellrc.text = [NSString stringWithFormat:@"%@ - %@", self.lrc.ti , self.lrc.ar];//设置第一句歌词 151 } 152 - (void)previous//上一首 153 { 154 self.indexMusicList == 0 ? self.indexMusicList = self.musicListArray.count - 1 : self.indexMusicList-- ;//第一首自动切换到最后一首 155 [self playerclear]; 156 [self addSource]; 157 [self startandpause]; 158 } 159 - (void)next//下一首 160 { 161 self.indexMusicList == (self.musicListArray.count - 1) ? (self.indexMusicList = 0) : self.indexMusicList++;//最后一首自动切换到第一首 162 [self playerclear]; 163 [self addSource]; 164 [self startandpause]; 165 } 166 - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag//播放结束后 播放下一首 167 { 168 flag ? [self next]:nil; 169 } 170 - (void)timeadd//更新滚动条 171 { 172 self.slider.value = self.player.currentTime/self.player.duration;//进度条工作 173 [self setTLableCur]; 174 self.indexLrc == self.lrc.lrcArrayTime.count ? self.labellrc.text = self.lrc.lrcArrayStr[self.indexLrc - 1]:fabs([self.lrc.lrcArrayTime[self.indexLrc] doubleValue] - self.player.currentTime) < 0.06?self.labellrc.text = self.lrc.lrcArrayStr[self.indexLrc++]:nil; //判断歌词是不是全部播放完了,是就显示:最后一句歌词 不是 就判断是不是有哪句歌词是当前应该播放的(时间差小于0.05s)有就设置播放,没有就不做任何处理 175 } 176 -(void)rotate//图片旋转 177 { 178 CGAffineTransform t=CGAffineTransformRotate(self.musicImg.transform, 0.01); 179 self.musicImg.transform=t; 180 } 181 - (void)updateValue//拖动进度条动作 182 { 183 self.player.currentTime = self.player.duration * self.slider.value; 184 [self setTLableCur]; 185 self.indexLrc = 0;//歌词数组遍历完成了 或者 当前指向的歌词的播放时间 比 当前歌曲播放时间大;就跳出循环 186 while(self.indexLrc != self.lrc.lrcArrayTime.count && [self.lrc.lrcArrayTime[self.indexLrc] doubleValue] < self.player.currentTime) 187 { 188 self.indexLrc++; 189 } 190 self.labellrc.text = self.lrc.lrcArrayStr[self.indexLrc-1>-1?self.indexLrc-1:0];//跳出循环的 就播放当前指向的前一句歌词 191 } 192 - (void)setTLableCur//设置当前播放时间 193 { 194 NSDateFormatter *formatter = [[NSDateFormatter alloc]init]; 195 [formatter setDateFormat:@"mm:ss"]; //格式化时间配置 196 self.tlablecur.text = [formatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:self.player.currentTime]]; //设置显示时间 197 } 198 - (void)didReceiveMemoryWarning { 199 [super didReceiveMemoryWarning]; 200 // Dispose of any resources that can be recreated. 201 } 202 @end
知识点解析:
1、
#import "LyricsAnalysis.h"
自己手写的歌词解析类,可以查看我的上一篇博客去看看实现,记得按照下面的更新更新类里面的修改部分;
2、懒加载,用了下,感觉还行,具体的不会细讲,反正就是一种不用你管的自动运行的机制,想详细了解的同学,自己看,我只是声明下,以免有没见过的看见不认识,
3、
CGAffineTransform t=CGAffineTransformRotate(self.musicImg.transform, 0.01);
self.musicImg.transform=t;
实现图片旋转,系统提供的类,
4、图片遮盖实现免切图的圆形;
音乐播放的时候的图片,切图太麻烦,巧妙地利用背景图,将背景图置于歌曲专辑图的上方,留下一块圆形空白,于是看到的就是圆形图片了,很容易理解的逻辑
5、歌词匹配的基本原理,是歌词应该播放的时间与当前歌曲播放的时间的差的绝对值足够小
6、拖动进度条歌词从第一句开始匹配,一直找到适当的位置为止,
7、plist 文件应用。
由于博客园上传文件大小限制,此处连接为百度云盘连接 不保证持续有效