iOS开发练习之UIPickerView实现歌词翻滚效果
麻雀虽小,五脏俱全.在平时的项目中,任何一个模块或者功能里其实都隐藏着许多我们平时注意不到的知识点,其实很多东西大家每天都在用,但很多时候都是知其然,而不知其所以然.时间久了,也就懒得去想到底是什么原因了,怎么实现的之类.回想自己的学习路程,也基本都这样混过来,实在愧对光阴,近日抽空,查看过往笔记,顺手写了个小代码练习,感觉温故知新.现分享代码,以供新手入门参考,尤其其中错误的部分也很有广泛性.同时也欢迎各路成精的老鸟们喷吐,能够指正,这样也促进我再进步一点.
ViewController.m文件如下:
1 #import "ViewController.h" 2 #import "Word.h" 3 #import "AudioPlayTool.h" 4 #import "NSString+CJZ.h" 5 6 7 @interface ViewController ()<UIPickerViewDataSource,UIPickerViewDelegate> 8 9 @property (nonatomic,strong) NSArray *wordsArray; // 存储对象word,word是根据歌词文件生成的一个对象,用来在PickerView显示一行的信息; 10 @property (nonatomic,assign) int index; // 播放索引; 11 @property (nonatomic,strong) CADisplayLink *playLink; // 定时器; 12 @property (nonatomic,strong) AudioPlayTool * playTool; // 播放类工具,用来播放歌曲, 13 14 @property (weak, nonatomic) IBOutlet UIPickerView *wordListPicker; // 显示歌词的PickerView 15 16 17 @end 18 19 @implementation ViewController 20 - (IBAction)nextClick { 21 [self.wordListPicker selectRow:self.index inComponent:0 animated:YES]; 22 } 23 24 25 - (AudioPlayTool *)playTool 26 { 27 if (_playTool == nil) { 28 _playTool = [[AudioPlayTool alloc]init]; 29 } 30 return _playTool; 31 } 32 33 - (CADisplayLink *)playLink 34 { 35 if (_playLink == nil) { 36 _playLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateInfo:)]; 37 } 38 return _playLink; 39 } 40 41 - (NSArray *)wordsArray 42 { 43 if (_wordsArray == nil) { 44 _wordsArray = [NSArray array]; 45 } 46 return _wordsArray; 47 } 48 49 - (void)viewDidLoad 50 { 51 [super viewDidLoad]; 52 NSString *path = [[NSBundle mainBundle]pathForResource:@"Set Fire To The Rain_歌词.lrc" ofType:nil]; 53 self.wordsArray = [[Word alloc] wordsWithFilePath:path]; 54 [self.playTool prepareAudioWithName:@"31071114.mp3"]; 55 [self.playTool play]; 56 [self.playLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; 57 58 } 59 60 #pragma mark - UIPickerView DataSource and Delegate; 61 62 - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component 63 { 64 return 40; 65 } 66 67 - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView 68 { 69 return 1; 70 } 71 - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component 72 { 73 return self.wordsArray.count; 74 75 } 76 77 78 - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view 79 { 80 UILabel *textLable = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 320, 40)]; 81 Word *textWord = self.wordsArray[row]; 82 textLable.text = textWord.text; 83 textLable.font = [UIFont systemFontOfSize:13]; 84 textLable.numberOfLines = 0; 85 return textLable; 86 } 87 - (void)updateInfo:(CADisplayLink *)display 88 { 89 AVAudioPlayer *player = self.playTool.audioPlay; 90 double currentTime = player.currentTime; 91 NSString *change2Time = [NSString getMinuteSecondWithSecond:currentTime]; 92 double compareTime = [NSString getTimeWithString:change2Time]; 93 94 for (int i = 0; i < self.wordsArray.count; i++) 95 { 96 Word *beginW = self.wordsArray[i]; 97 double wordTime = [NSString getTimeWithString:beginW.time]; 98 Word *nextW = nil; 99 int next = i + 1; 100 if (next < self.wordsArray.count) { 101 nextW = self.wordsArray[next]; 102 if (compareTime >= wordTime && compareTime <= [NSString getTimeWithString:nextW.time]) 103 { 104 dispatch_async(dispatch_get_main_queue(), ^{ 105 self.index = i + 1; 106 [self nextClick]; 107 }); 108 break; 109 } 110 } 111 } 112 } 113 114 115 116 @end
其中,加载歌词的文件是通过封装的Word类进行装换:
word.h
1 #import <Foundation/Foundation.h> 2 3 @interface Word : NSObject 4 @property (nonatomic,copy)NSString *time; 5 @property (nonatomic,copy)NSString *text; 6 7 + (instancetype)wordWithString:(NSString *)string; //工具方法,根据特定的字符串,生成word对象; 8 - (instancetype)initWithString:(NSString *)string; // 同上; 9 10 - (NSArray *)wordsWithFilePath:(NSString *)path; // 根据文件路径,生成包含多个word对象的数组; 11 12 @end
word.m
1 #import "Word.h" 2 3 @implementation Word 4 5 - (instancetype)initWithString:(NSString *)string 6 { 7 if (self = [super init]) { 8 NSRange rangeOne = NSMakeRange(1, 5); 9 self.time = [string substringWithRange:rangeOne]; 10 self.text = [string substringFromIndex:10]; 11 } 12 return self; 13 } 14 15 + (instancetype)wordWithString:(NSString *)string 16 { 17 return [[self alloc]initWithString:string]; 18 } 19 20 - (NSArray *)wordsWithFilePath:(NSString *)path 21 { 22 NSError *error = nil; 23 NSString *original = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error]; 24 NSArray *stringArray = [original componentsSeparatedByString:@"\n"]; 25 NSMutableArray *lastArray = [NSMutableArray array]; 26 for (NSString *string in stringArray) { 27 if ((string.length > @"[00:00:00]".length ) && [string hasPrefix:@"[0"]) { 28 [lastArray addObject:string]; 29 } 30 } 31 NSMutableArray *wordsArray = [NSMutableArray array]; 32 for (NSString *string in lastArray) { 33 Word *singleWord = [Word wordWithString:string]; 34 [wordsArray addObject:singleWord]; 35 } 36 return [wordsArray copy]; 37 } 38 @end
其中,播放音乐的工具类如下:
AVAudioPlayer.h
1 #import <Foundation/Foundation.h> 2 #import <AVFoundation/AVFoundation.h> 3 4 @class AVAudioPlayer ; 5 @interface AudioPlayTool : NSObject 6 7 @property (nonatomic,strong,readonly ) AVAudioPlayer *audioPlay; 8 9 - (void)prepareAudioWithName:(NSString *)name; 10 - (void)play; 11 - (void)stop; 12 - (void)pause; 13 14 @end
AVAudioPlayer.m
1 #import "AudioPlayTool.h" 2 3 4 @interface AudioPlayTool() 5 6 7 @end 8 9 @implementation AudioPlayTool 10 11 12 - (void)prepareAudioWithName:(NSString *)name 13 { 14 NSError *error = nil; 15 NSString *songPath = [[NSBundle mainBundle] pathForResource:name ofType:nil]; 16 AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:songPath] error:&error]; 17 if (error) { 18 return; 19 } 20 [player prepareToPlay]; 21 _audioPlay = player; 22 } 23 24 - (void)play 25 { 26 if (![_audioPlay isPlaying]) { 27 [self.audioPlay play]; 28 29 } 30 } 31 32 - (void)stop 33 { 34 [self.audioPlay stop]; 35 } 36 37 - (void)pause 38 { 39 if ([_audioPlay isPlaying]) { 40 [self.audioPlay pause]; 41 42 } 43 } 44 45 @end
自己写的一个字符串分类,
#import <Foundation/Foundation.h> @interface NSString (CJZ) /** * 返回分与秒的字符串 如:01:60 */ +(NSString *)getMinuteSecondWithSecond:(NSTimeInterval)time; +(NSTimeInterval) getTimeWithString:(NSString *)string; @end
.m部分:
#import "NSString+CJZ.h" @implementation NSString (CJZ) +(NSString *)getMinuteSecondWithSecond:(NSTimeInterval)time{ int minute = (int)time / 60; int second = (int)time % 60; if (second > 9) { return [NSString stringWithFormat:@"%d:%d",minute,second]; } return [NSString stringWithFormat:@"%d:0%d",minute,second]; } + (NSTimeInterval)getTimeWithString:(NSString *)string{ if (string.length == 5) { double first = [[string substringWithRange:NSMakeRange(1, 1)] doubleValue]; double second = [[string substringFromIndex:3] doubleValue]; return first + second * 0.01; } double first = [[string substringWithRange:NSMakeRange(0, 1)] doubleValue]; double second = [[string substringFromIndex:2] doubleValue]; return first + second * 0.01; } @end
整个代码在Xcode5.1.1环境,ARC下测试通过.
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。