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:@"
"];
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下测试通过.

运行截图:

    

补充截图^_^

原文地址:https://www.cnblogs.com/caios/p/3832500.html