首页 > 代码库 > iOS开发练习之UIPickerView实现歌词翻滚效果

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 *)string16 {17     return [[self alloc]initWithString:string];18 }19 20 - (NSArray *)wordsWithFilePath:(NSString *)path21 {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 AudioPlayTool10 11 12 - (void)prepareAudioWithName:(NSString *)name13 {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)play25 {26     if (![_audioPlay isPlaying]) {27         [self.audioPlay play];28     29     }30 }31 32 - (void)stop33 {34     [self.audioPlay stop];35 }36 37 - (void)pause38 {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下测试通过.