• 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下测试通过.

    运行截图:

        

    补充截图^_^

  • 相关阅读:
    Delphi单元文件之-防止程序重复执行
    cxGrid使用汇总2
    Delphi数组复制
    cxGrid使用汇总1
    Delphi XE5 android 获取网络状态
    xe5 android sample 中的 SimpleList 是怎样绑定的
    XE5 Android 开发数据访问手机端 解决乱码的办法
    设计模式之代理模式
    设计模式之单例模式及原型模式
    设计模式之工厂模式
  • 原文地址:https://www.cnblogs.com/caios/p/3832500.html
Copyright © 2020-2023  润新知