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

iOS开发练习之UIPickerView实现歌词翻滚效果

时间: 2024-11-08 19:24:01

iOS开发练习之UIPickerView实现歌词翻滚效果的相关文章

iOS开发UI篇—UIPickerView控件简单介绍

iOS开发UI篇—UIPickerView控件简单介绍 一.UIPickerView 控件 1.简单介绍: 2.示例代码 TXViewController.m文件 1 // Created by 鑫 on 14-10-15. 2 3 // Copyright (c) 2014年 梁镋鑫. All rights reserved. 4 5 // 6 7 8 9 #import "TXViewController.h" 10 11 12 13 @interface TXViewContro

iOS开发之剖析&quot;秘密&quot;App内容页面效果(二)

@前些天写了一篇"秘密"的Cell效果文章,但是与在工作中想要的效果还是有差距,而且扩展性很不好,于是重写封装,把整体视图都放到scrollView中,基本是和secret app 一模一样的效果了. @代码如下:(模糊效果的类就不写了,大家可以搜"UIImage+ImageEffects",还要导入Accelerate.framework) 1.MTSecretAppEffect.h #import <Foundation/Foundation.h>

iOS开发之剖析&quot;秘密&quot;App内容页面效果

最近在玩"秘密",发现点击主界面的Cell进去后的页面效果不错,就写了个Demo来演示下. 它主要效果:下拉头部视图放大,上拉视图模糊而且到一定位置固定不动,其他Cell可以继续上移. @封装的主要效果类:MTHeadEffect.m(.h文件省略,很简单的) #import "MTHeadEffect.h" #import <QuartzCore/QuartzCore.h> #import <Accelerate/Accelerate.h>

iOS开发之各种动画各种页面切面效果

因工作原因,有段时间没发表博客了,今天就发表篇博客给大家带来一些干货,切勿错过哦.今天所介绍的主题是关于动画的,在之前的博客中也有用到动画的地方,今天就好好的总结一下iOS开发中常用的动画.说道动画其中有一个是仿射变换的概念,至于怎么仿射的怎么变换的,原理如何等在本篇博客中不做赘述.今天要分享的是如和用动画做出我们要做的效果. 今天主要用到的动画类是CALayer下的CATransition至于各种动画类中如何继承的在这也不做赘述,网上的资料是一抓一大把.好废话少说切入今天的正题. 一.封装动画

iOS 8:【转】iOS开发之各种动画各种页面切面效果

源地址:http://www.cnblogs.com/ludashi/p/4160208.html 因工作原因,有段时间没发表博客了,今天就发表篇博客给大家带来一些干货,切勿错过哦.今天所介绍的主题是关于动画的,在之前的博客中也有用到动画的地方,今天就好好的总结一下iOS开发中常用的动画.说道动画其中有一个是仿射变换的概念,至于怎么仿射的怎么变换的,原理如何等在本篇博客中不做赘述.今天要分享的是如和用动画做出我们要做的效果. 今天主要用到的动画类是CALayer下的CATransition至于各

iOS开发-数据选择UIPickerView

UIPickerView开发一般选择区域或者分级数据的时候会使用到,类似于前端中用到树状结构,不过PC上一般都是从上到下的分级,使用UIPickView是从左到右实现,可以动态的设置UIPickView中中行列数据,将结果显示在文本输入框里,简单的定义一下数据源.通过声明协议捕获事件,展示结果,比较简单,进入正题. 页面布局 页面布局比较简单,一个UIPickerView,一个文本框: 头文件中的声明,实现了UIPickerViewDelegate,UIPickerViewDataSource协

iOS 开发仿网易云音乐歌词海报

使用网易云音乐也是一个巧合,我之前一直使用QQ音乐听歌,前几天下 app 手机内存告急.于是就把QQ音乐给卸载掉了,正好晚上朋友圈里有一个朋友用网易云音乐分享了一首歌曲,于是我也就尝试下载了网易云音乐,这一下载就让我从QQ音乐粉转黑了. 从设计的角度来看,网易云音乐的界面简洁,慷慨,不像kugou音乐一打开就是各种广告.让人心烦.也不像QQ音乐那样动不动就各种音质,各种冲钻(不为用户需求考虑.仅仅想赚钱,差评).最关键的是它推荐的歌真是好听,实在是太懂我了,真的是非常用心的在做音乐. 废话不多说

iOS开发技巧 - 使用UIPickerView来选择值

(Swift) import UIKit class ViewController: UIViewController, UIPickerViewDataSource { var picker: UIPickerView! override func viewDidLoad() { super.viewDidLoad() picker = UIPickerView() // select the current view controller as the data source of the

IOS开发-UIDatePicker和UIPickerView(拾取器)

外观及作用                     UIDatePicker和事件相关,用来设置时间,选择时间等.UIPickerView则是自定义的,可以用作下拉列表等 运行结果 本示例主要简示了这些拾取器的用法,效果图如下所示(改成Iphone4大小了):          构建概要 1.新建基本视图或者基于TabView的工程,如果是基本的工程,需要额外操作转换为TabView,方法为:打开Main.storyboard,选中视图,然后在Xcode的菜单中Edit->Ebeded in->