1 使用触控实现一个简易的画板

1.1 问题

触控(Touch)是一个UITouch类型的对象,当用户触摸了屏幕上的视图时自动被创建,通常使用触控实现绘图、涂鸦、手写等功能。本案例使用触控实现一个简易的画板,可以在画板上勾画出一条线,如图-1所示:

图-1

1.2 方案

首先在创建好的SingleViewApplication项目中创建一个画板类TRDrawView,继承至UIView,该类有一个NSMutableArray类型的属性points,用于存储手指触摸的轨迹也就是点。

其次在Stroyboard的场景中拖放一个View控件,和屏幕一样大小,然后将View的类型修改为TRDrawView。

然后在TRDrawView类中通过touchesBegan:、touchesMoved:方法获取到手指的触摸点,将点存储到points数组中。

最后在TRDrawView类中重写drawRect方法,该方法中根据手指的触摸轨迹points进行屏幕绘制。切记要在touchesMoved方法中调用setNeedDisplay刷新界面。

1.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建项目和画板类

首先在创建好的SingleViewApplication项目中创建一个画板类TRDrawView,继承至UIView,该类有一个NSMutableArray类型的属性points,用于存储手指触摸的轨迹也就是点,代码如下所示:

 
  1. @interface TRDrawView ()
  2. @property (strong, nonatomic) NSMutableArray *points;
  3. @end

然后从对象库中拖放一个View控件到Storyboard场景中,View控件的大小和屏幕一样。在右边栏的检查器三将View的类型设置为TRDrawView,如图-2所示:

图-2

步骤二:在TRDawView中获取手指触摸轨迹

在TRDrawView类中首先重写touchesBegan:,在该方法将points属性进行初始化,并获取当前手指的触摸点,存储到points数组中,代码如下所示:

 
  1. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
  2. {
  3. //初始化数组
  4. self.points = [@[]mutableCopy];
  5. //获取当前触摸点
  6. UITouch *touch = [touches anyObject];
  7. CGPoint point = [touch locationInView:self];
  8. //将点放进数组中
  9. NSValue *value = [NSValue valueWithCGPoint:point];
  10. [self.points addObject:value];
  11. }

然后再重写touchesMove:方法,在该方法中继续获取手指的当前触摸点,并将触摸点存储到points数组中,代码如下所示:

 
  1. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
  2. {
  3. //获取当前触摸点
  4. UITouch *touch = [touches anyObject];
  5. CGPoint point = [touch locationInView:self];
  6. //将点放进数组中
  7. NSValue *value = [NSValue valueWithCGPoint:point];
  8. [self.points addObject:value];
  9. }

步骤三:重写drawRect方法,进行屏幕绘制

在TRDrawView类中重写drawRect方法,该方法中根据手指的触摸轨迹points进行屏幕绘制,代码如下所示:

 
  1. - (void)drawRect:(CGRect)rect
  2. {
  3. UIBezierPath *path = [UIBezierPath bezierPath];
  4. NSValue *value = [self.points firstObject];
  5. [path moveToPoint:[value CGPointValue]];
  6. for (NSValue *value in self.points) {
  7. [path addLineToPoint:[value CGPointValue]];
  8. }
  9. path.lineWidth = 4;
  10. [[UIColor redColor]setStroke];
  11. [path stroke];
  12. }

最后要在touchesMoved:和touchesEnded:方法中调用setNeedDisplay刷新界面,代码如下所示:

 
  1. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
  2. {
  3. //获取当前触摸点
  4. UITouch *touch = [touches anyObject];
  5. CGPoint point = [touch locationInView:self];
  6. //将点放进数组中
  7. NSValue *value = [NSValue valueWithCGPoint:point];
  8. [self.points addObject:value];
  9. //刷新界面
  10. [self setNeedsDisplay];
  11. }
  12. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
  13. {
  14. [self setNeedsDisplay];
  15. }

1.4 完整代码

本案例中,TRDrawView.m文件中的完整代码如下所示:

2 使用纯代码进行界面布局

2.1 问题

纯代码布局就是重写布局方法viewDidLayoutSubviews,在该方法内部计算每个子视图的frame属性。本案例将学习如何使用纯代码进行布局,使界面上的Button和Label控件始终保持在固定的位置,如图-3、图-4所示:

图-3

图-4

2.2 方案

首先创建一个SingleViewApplication项目,将自动布局功能关闭。

在Stroyboard的场景中拖放两个Button控件和一个Label控件,Button放置在屏幕的上方,并且大小一样,Label控件放置在屏幕的右下角。

然后在TRViewController类中重写布局方法viewDidLayoutSubviews,在该方法中根据父视图的bounds计算Button和Label的frame。

2.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建项目,添加控件

首先创建一个SingleViewApplication项目,在右边栏的检查器一中将自动布局功能关闭,如图-5所示:

图-5

在Stroyboard的场景中拖放两个Button控件和一个Label控件,Button放置在屏幕的上方,并且大小一样,Label控件放置在屏幕的右下角,如图-6所示:

图-6

步骤二:重写布局方法viewDidLayoutSubviews,进行界面布局

将Storyboard中的Button控件和Label控件关联成TRViewController的私有属性,代码如下所示:

 
  1. @interface TRViewController ()
  2. @property (weak, nonatomic) IBOutlet UIButton *button1;
  3. @property (weak, nonatomic) IBOutlet UIButton *button2;
  4. @property (weak, nonatomic) IBOutlet UILabel *label;
  5. @end

在TRViewController类中重写布局方法viewDidLayoutSubviews,在该方法中根据父视图的bounds计算Button和Label的frame,代码如下所示:

 
  1. - (void)viewDidLayoutSubviews
  2. {
  3. [super viewDidLayoutSubviews];
  4. CGFloat buttonWidth = (self.view.bounds.size.width - 20 - 20 - 10) * 0.5;
  5. CGRect frame = CGRectMake(20, self.button1.frame.origin.y, buttonWidth, 40);
  6. self.button1.frame = frame;
  7. frame = CGRectMake(self.button1.frame.size.width+30, self.button2.frame.origin.y, buttonWidth, 40);
  8. self.button2.frame = frame;
  9. frame = self.label.frame;
  10. self.label.frame = CGRectMake(self.view.bounds.size.width-20-frame.size.width, self.view.bounds.size.height-20-frame.size.height, frame.size.width, frame.size.height);
  11. }

2.4 完整代码

本案例中,TRViewController.m文件中的完整代码如下所示:

 
  1. #import "TRViewController.h"
  2. @interface TRViewController ()
  3. @property (weak, nonatomic) IBOutlet UIButton *button1;
  4. @property (weak, nonatomic) IBOutlet UIButton *button2;
  5. @property (weak, nonatomic) IBOutlet UILabel *label;
  6. @end
  7. @implementation TRViewController
  8. - (void)viewDidLayoutSubviews
  9. {
  10. [super viewDidLayoutSubviews];
  11. CGFloat buttonWidth = (self.view.bounds.size.width - 20 - 20 - 10) * 0.5;
  12. CGRect frame = CGRectMake(20, self.button1.frame.origin.y, buttonWidth, 40);
  13. self.button1.frame = frame;
  14. frame = CGRectMake(self.button1.frame.size.width+30, self.button2.frame.origin.y, buttonWidth, 40);
  15. self.button2.frame = frame;
  16. frame = self.label.frame;
  17. self.label.frame = CGRectMake(self.view.bounds.size.width-20-frame.size.width, self.view.bounds.size.height-20-frame.size.height, frame.size.width, frame.size.height);
  18. }
  19. @end

3 根据上边栏和下边栏的高度进行布局

3.1 问题

从iOS7开始,视图控制器会渗透到各种Bar下面,包括:NavigationBar、ToolBar、TabBar、StatusBar等;这些Bar会挤占视图的空间,在布局时就需要根据各种Bar所挤占的空间大小来计算控件的frame,本案例直接在上一个案例的基础上实现,根据上边栏和下边栏的高度对界面进行布局,如图-7、图-8所示:

图-7

图-8

3.2 方案

首先在上一个案例的基础上增加一个NavigationController和TabBarController,在界面的中间拖放一个Button控件,标题设置为“隐藏NavigationBar”,并将Button控件关联成TRViewController的私有方法hideNavigationBar。

然后在TRViewController类中重写布局方法viewDidLayoutSubviews,在该方法中根据父视图的bounds和上下边栏的高度计算Button和Label的frame。

3.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建项目,添加按钮控件

在上一个案例的基础上增加一个NavigationController和TabBarController,在界面的中间拖放一个Button控件,标题设置为“隐藏NavigationBar”,如图-9所示:

图-9

然后将Button控件关联成TRViewController的私有方法hideNavigationBar,该方法的功能是将导航栏隐藏或显示,代码如下所示:

 
  1. - (IBAction)hideNavigationBar
  2. {
  3. self.navigationController.navigationBarHidden = !self.navigationController.navigationBarHidden;
  4. }

步骤二:重写布局方法viewDidLayoutSubviews,进行界面布局

在TRViewController类中重写布局方法viewDidLayoutSubviews,在该方法中根据先通过属性self.topLayoutGuide.length和self.bottomLayoutGuide.length获取到上下边栏的高度,然后再通过父视图的bounds和上下边栏的高度计算出Button和Label的frame,代码如下所示:

 
  1. - (void)viewDidLayoutSubviews
  2. {
  3. [super viewDidLayoutSubviews];
  4. CGFloat buttonWidth = (self.view.bounds.size.width - 20 - 20 - 10) * 0.5;
  5. //从iOS7开始,可以随时知道VC的上面和下面被各种Bar占据了多少的空间
  6. CGFloat top = self.topLayoutGuide.length;
  7. CGRect frame = CGRectMake(20, top+10, buttonWidth, 40);
  8. self.button1.frame = frame;
  9. frame.origin.x += buttonWidth + 10;
  10. self.button2.frame = frame;
  11. //下面的各种Bar(TabBar或ToolBar)占了VC多高的空间
  12. CGFloat bottom = self.bottomLayoutGuide.length;
  13. frame = self.label.frame;
  14. frame = CGRectMake(self.view.bounds.size.width - 20 - frame.size.width , self.view.bounds.size.height - 10 - frame.size.height - bottom, frame.size.width, frame.size.height);
  15. self.label.frame = frame;
  16. frame = self.hideButton.frame;
  17. frame.origin.x = self.view.bounds.size.width * 0.5 - frame.size.width * 0.5;
  18. frame.origin.y = self.view.bounds.size.height * 0.5 - frame.size.height * 0.5;
  19. self.hideButton.frame = frame;
  20. }

3.4 完整代码

本案例中,TRViewController.m文件中的完整代码如下所示:

 
  1. #import "TRViewController.h"
  2. @interface TRViewController ()
  3. @property (weak, nonatomic) IBOutlet UIButton *button1;
  4. @property (weak, nonatomic) IBOutlet UIButton *button2;
  5. @property (weak, nonatomic) IBOutlet UILabel *label;
  6. @property (weak, nonatomic) IBOutlet UIButton *hideButton;
  7. @end
  8. @implementation TRViewController
  9. - (IBAction)hideNavigationBar
  10. {
  11. self.navigationController.navigationBarHidden = !self.navigationController.navigationBarHidden;
  12. }
  13. - (void)viewDidLayoutSubviews
  14. {
  15. [super viewDidLayoutSubviews];
  16. CGFloat buttonWidth = (self.view.bounds.size.width - 20 - 20 - 10) * 0.5;
  17. //从iOS7开始,可以随时知道VC的上面和下面被各种Bar占据了多少的空间
  18. CGFloat top = self.topLayoutGuide.length;
  19. CGRect frame = CGRectMake(20, top+10, buttonWidth, 40);
  20. self.button1.frame = frame;
  21. frame.origin.x += buttonWidth + 10;
  22. self.button2.frame = frame;
  23. //下面的各种Bar(TabBar或ToolBar)占了VC多高的空间
  24. CGFloat bottom = self.bottomLayoutGuide.length;
  25. frame = self.label.frame;
  26. frame = CGRectMake(self.view.bounds.size.width - 20 - frame.size.width , self.view.bounds.size.height - 10 - frame.size.height - bottom, frame.size.width, frame.size.height);
  27. self.label.frame = frame;
  28. frame = self.hideButton.frame;
  29. frame.origin.x = self.view.bounds.size.width * 0.5 - frame.size.width * 0.5;
  30. frame.origin.y = self.view.bounds.size.height * 0.5 - frame.size.height * 0.5;
  31. self.hideButton.frame = frame;
  32. }
  33. @end

4 演示绘制图形的布局

4.1 问题

使用纯代码布局并且AutoLayout关闭的状态下,在drawRect方法中绘制的图形,在视图大小发生变化时图形会失真,本案例学习绘制图形的布局如图-10,图-11所示:

图-10

图-11

4.2 方案

首先在创建好的项目中将自动布局功能关闭,再创建一个TRView类,继承至UIView。

其次在Stroyboard的场景中拖放一个View控件,和屏幕一样大小,然后将View的类型修改为TRView。

然后在TRView类中重写drawRect方法,在屏幕左上方绘制一个三角形。

最后将TRView的contentMode属性设置成Redraw,即可实现绘制的布局,屏幕切换或者变化绘制的图形也不会失真。

4.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建TRView类,绘制图像

首先在创建好的项目中将自动布局功能关闭,创建一个TRView类,继承至UIView,用于绘制图形。在Storyboard中拖放一个View控件,和屏幕同等大小,并将View的类型修改为TRView,如图-12所示:

图-12

然后将View控件关联成TRViewController的私有属性myView,代码如下所示:

 
  1. @interface TRViewController ()
  2. @property (weak, nonatomic) IBOutlet TRView *myView;
  3. @end

最后在TRView类中重写drawRect方法,在屏幕左上方绘制一个三角形,代码如下所示:

 
  1. - (void)drawRect:(CGRect)rect
  2. {
  3. UIBezierPath *path = [UIBezierPath bezierPath];
  4. [path moveToPoint:CGPointMake(20, 20)];
  5. [path addLineToPoint:CGPointMake(20, 120)];
  6. [path addLineToPoint:CGPointMake(120, 20)];
  7. [path closePath];
  8. path.lineWidth = 4;
  9. [[UIColor redColor] setStroke];
  10. [path stroke];
  11. }

步骤二:进行绘制布局

完成绘制代码,运行程序可见屏幕左上方有一个三角形,但是当切换成横屏时发现三角形失真,如图-13所示:

图-13

解决的办法是,当视图大小发生变化时,进行重新绘制图形,即在布局方法viewDidLayoutSubviews里面调用setNeedDisplay方法即可,代码如下所示:

 
  1. - (void)viewDidLayoutSubviews
  2. {
  3. [super viewDidLayoutSubviews];
  4. [self.myView setNeedsDisplay];
  5. }

但是通常直接将myView的contentMode属性设置为Redraw即可实现绘制布局,相当于调用了上面的代码,将myView的contentMode属性设置为Redraw有两个方法,第一种可以直接通过代码设置,代码如下所示:

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. self.myView.contentMode = UIViewContentModeRedraw;
  5. }

第二种方法可以直接在Stroyboard中设置,右边栏的检查器四中将Mode选项设置为Redraw即可,如图-14所示:

图-14

将contentMode设置为Redraw之后就不需要再写布局代码,此时切换屏幕绘制图形就不会失真了。

4.4 完整代码

本案例中,TRViewController.m文件中的完整代码如下所示:

 
  1. #import "TRViewController.h"
  2. #import "TRView.h"
  3. @interface TRViewController ()
  4. @property (weak, nonatomic) IBOutlet TRView *myView;
  5. @end
  6. @implementation TRViewController
  7. - (void)viewDidLoad
  8. {
  9. [super viewDidLoad];
  10. self.myView.contentMode = UIViewContentModeRedraw;
  11. }
  12. //- (void)viewDidLayoutSubviews
  13. //{
  14. // [super viewDidLayoutSubviews];
  15. // [self.myView setNeedsDisplay];
  16. //}
  17. @end

本案例中,TRView.m文件中的完整代码如下所示:

 
  1. #import "TRView.h"
  2. @implementation TRView
  3. - (void)drawRect:(CGRect)rect
  4. {
  5. UIBezierPath *path = [UIBezierPath bezierPath];
  6. [path moveToPoint:CGPointMake(20, 20)];
  7. [path addLineToPoint:CGPointMake(20, 120)];
  8. [path addLineToPoint:CGPointMake(120, 20)];
  9. [path closePath];
  10. path.lineWidth = 4;
  11. [[UIColor redColor] setStroke];
  12. [path stroke];
  13. }
  14. @end

5 对乐库项目的播放列表单元格进行布局

5.1 问题

视图自身也可以使用布局方法layoutSubviews对自己的子视图进行布局,本案例使用视图的layoutSubviews方法给乐库项目的播放列表单元格进行布局,如图-15所示:

图-15

5.2 方案

首先创建一个SingleViewApplication项目,将Xcode自带的TRViewController类删除,创建一个TRMusicsTableViewController类,继承至UITableViewController,该类有一个NSArray类型的属性musics用于存储歌曲数据源。

再将Storyboard中自带的场景删除,拖放一个TableViewController到界面中,嵌入一个NavigaitionController。在右边栏的检查器中将TableViewController设置为动态表视图,并和TRMusicsTableViewController类进行绑定。

其次创建一个带有xib的TRMusicCell类,继承至UITableViewCell,在xib文件中进行自定义cell,往cell的contentView视图上拖放所需要的控件。

首先在cell的上方拖放一个Label控件,用于显示歌曲的名字。在cell的下方依次拖放两个ImageView控件和两个Label控件,两个ImageView控件分别用于表示歌曲是否为本地歌曲和是否高清。两个Label控件分别用于显示歌曲的信息和时长。

调整好cell上面各个控件的大小,将个控件关联为TRMusicCell的属性musicNameLabel、albumAndArtistLabel、durationLabel、downloadedImageView以及hdImageView。

然后再创建一个TRMusic类用于存储歌曲的相关信息,该类继承至NSObject,有五个属性,分别为:

NSString类型的name,用于记录歌曲名称;

NSString类型的album,用于记录歌曲所属专辑;

NSString类型的artist,用于记录歌曲的演唱者;

NSString类型的duration,用于记录歌曲的时长;

BOOL类型的highQuality和downloaded,分别用于记录是否高清和是否本地下载。

我们创建一个TRMusicGroup类,用于生成一组模拟的歌曲数据。

最后在TRMusicCell类中定义一个TRMusic类型属性music,用于存储单元格需要展示的歌曲。重写layoutSubviews方法,进行cell的界面布局,该方法中会根据每首歌曲的信息,计算子视图的frame进行布局。

在TRMusicTableViewController类注册Cell,回答三问给表视图加载歌曲数据。

5.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建播放列表项目

首先创建一个SingleViewApplication项目,将Xcode自带的TRViewController类删除,创建一个TRMusicsTableViewController类,继承至UITableViewController,该类有一个NSArray类型的属性musics用于存储歌曲数据源,代码如下所示:

  1. @interface TRMusicTableViewController : UITableViewController
  2. @property (strong, nonatomic) NSArray *musics;
  3. @end

然后将Storyboard中自带的场景删除,拖放一个TableViewController到界面中,嵌入一个NavigaitionController。在右边栏的检查器中将TableViewController设置为动态表视图,并和TRMusicsTableViewController类进行绑定,如图-16所示:

图-16

为了能更灵活的使用自定义cell,由于本案例使用xib的方式进行自定义cell,所以将Storyboard中表视图自带的cell对象删除,如图-17所示:

图-17

步骤二:创建TRMusicCell类,自定义Cell

首先创建一个带有xib的TRMusicCell类,继承至UITableViewCell,在xib文件中进行自定义cell,往cell的contentView视图上拖放所需要的控件。

先在cell的上方拖放一个Label控件,用于显示歌曲的名字。

再在cell的下方依次拖放两个ImageView控件和两个Label控件,两个ImageView控件分别用于表示歌曲是否为本地歌曲和是否高清。两个Label控件分别用于显示歌曲的信息和时长。

设置好cell上面各个控件的大小和属性,如图-18所示:

图-18

最后将cell上的各个控件关联为TRMusicCell的属性musicNameLabel、albumAndArtistLabel、durationLabel、downloadedImageView以及hdImageView,代码如下所示:

 
  1. @interface TRMusicCell ()
  2. @property (weak, nonatomic) IBOutlet UILabel *musicNameLabel;
  3. @property (weak, nonatomic) IBOutlet UILabel *albumAndArtistLabel;
  4. @property (weak, nonatomic) IBOutlet UILabel *durationLabel;
  5. @property (weak, nonatomic) IBOutlet UIImageView *downloadedImageView;
  6. @property (weak, nonatomic) IBOutlet UIImageView *hdImageView;
  7. @end

步骤三:创建TRMusic类和歌曲模拟数据

首先创建一个TRMusic类用于存储歌曲的相关信息,该类继承至NSObject,有五个属性,分别为:

NSString类型的name,用于记录歌曲名称;

NSString类型的album,用于记录歌曲所属专辑;

NSString类型的artist,用于记录歌曲的演唱者;

NSString类型的duration,用于记录歌曲的时长;

BOOL类型的highQuality和downloaded,分别用于记录是否高清和是否本地下载。

代码如下所示:

 
  1. @interface TRMusic : NSObject
  2. @property (nonatomic, copy) NSString * name;
  3. @property (nonatomic, copy) NSString * album;
  4. @property (nonatomic, copy) NSString * artist;
  5. @property (nonatomic) NSTimeInterval duration;
  6. @property (nonatomic) BOOL highQuality;
  7. @property (nonatomic) BOOL downloaded;
  8. @end

然后再创建一个TRMusicGroup类,该类提供一个静态方法fakeData,用于生成一组模拟的歌曲数据,代码如下所示:

 
  1. + (NSArray *) fakeData
  2. {
  3. NSMutableArray * musics = nil;
  4. TRMusic * music = nil;
  5. musics = [NSMutableArray array];
  6. music = [[TRMusic alloc] init];
  7. music.name = @"Burn";
  8. music.album = @"Burn - Single";
  9. music.artist = @"Ellie Goulding";
  10. music.duration = [self durationWithMinutes:3 andSeconds:51];
  11. music.downloaded = YES;
  12. music.highQuality = NO;
  13. [musics addObject:music];
  14. music = [[TRMusic alloc] init];
  15. music.name = @"Summertime Sadness (Cedric Gervais Remix)";
  16. music.album = @"Summertime Sadness (Cedric Gervais Remix) - Single";
  17. music.artist = @"Lana Del Rey";
  18. music.duration = [self durationWithMinutes:6 andSeconds:52];
  19. music.downloaded = YES;
  20. music.highQuality = YES;
  21. [musics addObject:music];
  22. music = [[TRMusic alloc] init];
  23. music.name = @"Spectrum";
  24. music.album = @"Clarity";
  25. music.artist = @"Zedd";
  26. music.duration = [self durationWithMinutes:4 andSeconds:3];
  27. music.downloaded = YES;
  28. music.highQuality = YES;
  29. [musics addObject:music];
  30. music = [[TRMusic alloc] init];
  31. music.name = @"It's Time";
  32. music.album = @"It’s Time";
  33. music.artist = @"Imagine Dragons";
  34. music.duration = [self durationWithMinutes:4 andSeconds:0];
  35. music.downloaded = NO;
  36. music.highQuality = YES;
  37. [musics addObject:music];
  38. music = [[TRMusic alloc] init];
  39. music.name = @"Dancing in The Moonlight";
  40. music.album = @"Dancing In The Moonlight: The Best Of Toploader";
  41. music.artist = @"Toploader";
  42. music.duration = [self durationWithMinutes:3 andSeconds:53];
  43. music.downloaded = YES;
  44. music.highQuality = YES;
  45. [musics addObject:music];
  46. music = [[TRMusic alloc] init];
  47. music.name = @"Thinking About You (feat. Ayah Marar)";
  48. music.album = @"18 Months (Deluxe Edition)";
  49. music.artist = @"Calvin Harris";
  50. music.duration = [self durationWithMinutes:4 andSeconds:8];
  51. music.downloaded = YES;
  52. music.highQuality = YES;
  53. [musics addObject:music];
  54. music = [[TRMusic alloc] init];
  55. music.name = @"You Make Me (feat. Salem Al Fakir)";
  56. music.album = @"True";
  57. music.artist = @"Avicii";
  58. music.duration = [self durationWithMinutes:3 andSeconds:51];
  59. music.downloaded = YES;
  60. music.highQuality = NO;
  61. [musics addObject:music];
  62. music = [[TRMusic alloc] init];
  63. music.name = @"Safe and Sound";
  64. music.album = @"Capital Cities EP";
  65. music.artist = @"Capital Cities";
  66. music.duration = [self durationWithMinutes:3 andSeconds:51];
  67. music.downloaded = YES;
  68. music.highQuality = NO;
  69. [musics addObject:music];
  70. music = [[TRMusic alloc] init];
  71. music.name = @"Reaching Out";
  72. music.album = @"Welcome Reality (Deluxe Version)";
  73. music.artist = @"nero";
  74. music.duration = [self durationWithMinutes:3 andSeconds:51];
  75. music.downloaded = YES;
  76. music.highQuality = NO;
  77. [musics addObject:music];
  78. music = [[TRMusic alloc] init];
  79. music.name = @"Recover";
  80. music.album = @"Recover - EP";
  81. music.artist = @"CHVRCHES";
  82. music.duration = [self durationWithMinutes:3 andSeconds:51];
  83. music.downloaded = YES;
  84. music.highQuality = NO;
  85. [musics addObject:music];
  86. music = [[TRMusic alloc] init];
  87. music.name = @"Hold On, We're Going Home (feat. Majid Jordan)";
  88. music.album = @"Hold On, We're Going Home (feat. Majid Jordan) - Single";
  89. music.artist = @"Drake";
  90. music.duration = [self durationWithMinutes:3 andSeconds:51];
  91. music.downloaded = YES;
  92. music.highQuality = NO;
  93. [musics addObject:music];
  94. music = [[TRMusic alloc] init];
  95. music.name = @"The Mother We Share";
  96. music.album = @"The Mother We Share - Single";
  97. music.artist = @"CHVRCHES";
  98. music.duration = [self durationWithMinutes:3 andSeconds:51];
  99. music.downloaded = YES;
  100. music.highQuality = NO;
  101. [musics addObject:music];
  102. music = [[TRMusic alloc] init];
  103. music.name = @"Promises";
  104. music.album = @"nero";
  105. music.artist = @"Promises - EP";
  106. music.duration = [self durationWithMinutes:3 andSeconds:51];
  107. music.downloaded = YES;
  108. music.highQuality = NO;
  109. [musics addObject:music];
  110. music = [[TRMusic alloc] init];
  111. music.name = @"Alone Together";
  112. music.album = @"Save Rock and Roll";
  113. music.artist = @"Fall Out Boy";
  114. music.duration = [self durationWithMinutes:3 andSeconds:51];
  115. music.downloaded = YES;
  116. music.highQuality = NO;
  117. [musics addObject:music];
  118. music = [[TRMusic alloc] init];
  119. music.name = @"Reload (Radio Edit)";
  120. music.album = @"Reload (Radio Edit) - Single";
  121. music.artist = @"Sebastian Ingrosso";
  122. music.duration = [self durationWithMinutes:3 andSeconds:51];
  123. music.downloaded = YES;
  124. music.highQuality = NO;
  125. [musics addObject:music];
  126. music = [[TRMusic alloc] init];
  127. music.name = @"I Love It (feat. Charli XCX)";
  128. music.album = @"Iconic";
  129. music.artist = @"Icona Pop";
  130. music.duration = [self durationWithMinutes:3 andSeconds:51];
  131. music.downloaded = YES;
  132. music.highQuality = NO;
  133. [musics addObject:music];
  134. music = [[TRMusic alloc] init];
  135. music.name = @"Feel the Love";
  136. music.album = @"Feel the Love (feat. John Newman) [Remixes] - EP";
  137. music.artist = @"Rudimental";
  138. music.duration = [self durationWithMinutes:3 andSeconds:51];
  139. music.downloaded = YES;
  140. music.highQuality = NO;
  141. [musics addObject:music];
  142. music = [[TRMusic alloc] init];
  143. music.name = @"Goin' Crazy (feat. Robbie Williams)";
  144. music.album = @"Goin' Crazy (feat. Robbie Williams) - Single";
  145. music.artist = @"Dizzee Rascal";
  146. music.duration = [self durationWithMinutes:3 andSeconds:51];
  147. music.downloaded = YES;
  148. music.highQuality = NO;
  149. [musics addObject:music];
  150. music = [[TRMusic alloc] init];
  151. music.name = @"Still Into You";
  152. music.album = @"Paramore";
  153. music.artist = @"Paramore";
  154. music.duration = [self durationWithMinutes:3 andSeconds:51];
  155. music.downloaded = YES;
  156. music.highQuality = NO;
  157. [musics addObject:music];
  158. music = [[TRMusic alloc] init];
  159. music.name = @"Heart Attack";
  160. music.album = @"Demi";
  161. music.artist = @"Demi Lovato";
  162. music.duration = [self durationWithMinutes:3 andSeconds:51];
  163. music.downloaded = YES;
  164. music.highQuality = NO;
  165. [musics addObject:music];
  166. music = [[TRMusic alloc] init];
  167. music.name = @"Explosions";
  168. music.album = @"Halcyon (Deluxe Edition)";
  169. music.artist = @"Ellie Goulding";
  170. music.duration = [self durationWithMinutes:3 andSeconds:51];
  171. music.downloaded = YES;
  172. music.highQuality = NO;
  173. [musics addObject:music];
  174. music = [[TRMusic alloc] init];
  175. music.name = @"I Need Your Love (feat. Ellie Goulding)";
  176. music.album = @"I Need Your Love";
  177. music.artist = @"Calvin Harris";
  178. music.duration = [self durationWithMinutes:3 andSeconds:51];
  179. music.downloaded = YES;
  180. music.highQuality = NO;
  181. [musics addObject:music];
  182. music = [[TRMusic alloc] init];
  183. music.name = @"Starry Eyed";
  184. music.album = @"Bright Lights";
  185. music.artist = @"Ellie Goulding";
  186. music.duration = [self durationWithMinutes:3 andSeconds:51];
  187. music.downloaded = YES;
  188. music.highQuality = NO;
  189. [musics addObject:music];
  190. music = [[TRMusic alloc] init];
  191. music.name = @"Lights (Single Version)";
  192. music.album = @"Bright Lights";
  193. music.artist = @"Ellie Goulding";
  194. music.duration = [self durationWithMinutes:3 andSeconds:51];
  195. music.downloaded = YES;
  196. music.highQuality = NO;
  197. [musics addObject:music];
  198. music = [[TRMusic alloc] init];
  199. music.name = @"Who's That Chick?";
  200. music.album = @"Who's That Chick - Single";
  201. music.artist = @"David Guetta";
  202. music.duration = [self durationWithMinutes:2 andSeconds:47];
  203. music.downloaded = YES;
  204. music.highQuality = NO;
  205. [musics addObject:music];
  206. TRMusicGroup * g1 = [[TRMusicGroup alloc] init];
  207. g1.name = @"国外单曲";
  208. g1.musics = [musics copy];
  209. g1.state = TRMusicGroupStateDownloaded;
  210. musics = [NSMutableArray array];
  211. music = [[TRMusic alloc] init];
  212. music.name = @"致青春";
  213. music.album = @"致青春";
  214. music.artist = @"王菲";
  215. music.duration = [self durationWithMinutes:3 andSeconds:18];
  216. music.downloaded = NO;
  217. music.highQuality = NO;
  218. [musics addObject:music];
  219. music = [[TRMusic alloc] init];
  220. music.name = @"好汉歌";
  221. music.album = @"六十年代生人";
  222. music.artist = @"刘欢";
  223. music.duration = [self durationWithMinutes:3 andSeconds:41];
  224. music.downloaded = NO;
  225. music.highQuality = YES;
  226. [musics addObject:music];
  227. music = [[TRMusic alloc] init];
  228. music.name = @"忐忑";
  229. music.album = @"自由鸟";
  230. music.artist = @"龚琳娜";
  231. music.duration = [self durationWithMinutes:4 andSeconds:03];
  232. music.downloaded = NO;
  233. music.highQuality = YES;
  234. [musics addObject:music];
  235. music = [[TRMusic alloc] init];
  236. music.name = @"爱情买卖";
  237. music.album = @"我们的爱我不放手";
  238. music.artist = @"慕容晓晓";
  239. music.duration = [self durationWithMinutes:3 andSeconds:31];
  240. music.downloaded = NO;
  241. music.highQuality = YES;
  242. [musics addObject:music];
  243. music = [[TRMusic alloc] init];
  244. music.name = @"法海你不懂爱";
  245. music.album = @"法海你不懂爱 - 单曲";
  246. music.artist = @"龚琳娜";
  247. music.duration = [self durationWithMinutes:3 andSeconds:33];
  248. music.downloaded = NO;
  249. music.highQuality = NO;
  250. [musics addObject:music];
  251. music = [[TRMusic alloc] init];
  252. music.name = @"最炫民族风";
  253. music.album = @"我们的爱我不放手";
  254. music.artist = @"凤凰传奇";
  255. music.duration = [self durationWithMinutes:4 andSeconds:46];
  256. music.downloaded = NO;
  257. music.highQuality = YES;
  258. [musics addObject:music];
  259. music = [[TRMusic alloc] init];
  260. music.name = @"金箍棒";
  261. music.album = @"金箍棒 - 单曲";
  262. music.artist = @"龚琳娜";
  263. music.duration = [self durationWithMinutes:2 andSeconds:52];
  264. music.downloaded = NO;
  265. music.highQuality = NO;
  266. [musics addObject:music];
  267. TRMusicGroup * g2 = [[TRMusicGroup alloc] init];
  268. g2.name = @"国内神曲";
  269. g2.musics = [musics copy];
  270. g2.state = TRMusicGroupStateNormal;
  271. TRMusicGroup * g3 = [[TRMusicGroup alloc] init];
  272. g3.name = @"Calvin Harris 专辑";
  273. g3.musics = @[];
  274. g3.state = TRMusicGroupStateNormal;
  275. TRMusicGroup * g4 = [[TRMusicGroup alloc] init];
  276. g4.name = @"Ellie Gounding 专辑";
  277. g4.musics = @[];
  278. g4.state = TRMusicGroupStateNormal;
  279. return @[g1, g2, g3, g4];
  280. }

步骤四:进行自定义cell布局

首先在TRMusicTableViewController类注册Cell,并在TRAppDelegate中对属性musics进行初始化,获取到模拟的歌曲数据,代码如下所示:

  1. //在TRAppDelegate中进行musics属性的初始化
  2. -(BOOL)application:(UIApplication *)application
  3. didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  4. {
  5. NSArray *musicGroups = [TRMusicGroup fakeData];
  6. TRMusicGroup *group = musicGroups[0];
  7. UINavigationController *navi = (UINavigationController *)self.window.rootViewController;
  8. TRMusicTableViewController *musicTVC = (TRMusicTableViewController *) navi.topViewController;
  9. musicTVC.musics = group.musics;
  10. return YES;
  11. }
  12. //在TRMusicsTableViewController中注册cell
  13. - (void)viewDidLoad
  14. {
  15. [super viewDidLoad];
  16. [self.tableView registerNib:[UINib nibWithNibName: @"TRMusicCell" bundle:nil] forCellReuseIdentifier:musicCellIdentifier];
  17. }

然后在TRMusicCell类中定义一个TRMusic类型属性music,用于存储单元格需要展示的歌曲,代码如下所示:

  1. //TRMusicCell.h文件中定义属性music
  2. @interface TRMusicCell : UITableViewCell
  3. @property (strong, nonatomic) TRMusic *music;
  4. @end

在TRMusicCell重写layoutSubviews方法,进行cell的界面布局,该方法中会根据每首歌曲的信息,计算子视图的frame进行布局,代码如下所示:

 
  1. - (void)layoutSubviews
  2. {
  3. [super layoutSubviews];
  4. CGFloat x = self.downloadedImageView.frame.origin.x;
  5. if (self.music.downloaded){
  6. x += 20;
  7. }
  8. if (self.music.highQuality) {
  9. CGRect frame = self.hdImageView.frame;
  10. frame.origin.x = x;
  11. self.hdImageView.frame = frame;
  12. x += 20;
  13. }
  14. CGRect frame = self.albumAndArtistLabel.frame;
  15. frame.origin.x = x;
  16. self.albumAndArtistLabel.frame = frame;
  17. }

歌曲的高清和下载图标需要根据歌曲的相关信息进行显示,可以将此部分功能通过重写music的setter方法来实现,代码如下所示:

 
  1. //TRMusicCell.m文件候中重写music的setter方法
  2. - (void)setMusic:(TRMusic *)music
  3. {
  4. _music = music;
  5. self.musicNameLabel.text = music.name;
  6. self.albumAndArtistLabel.text = [NSString stringWithFormat:@"%@ - %@", music.album, music.artist];
  7. self.durationLabel.text = [NSString stringWithFormat:@"%d:%02d", (int)music.duration/60, (int)music.duration%60];
  8. self.downloadedImageView.hidden = !music.downloaded;
  9. self.hdImageView.hidden = !music.highQuality;
  10. //根据是否高清或下载状态,需要重新布局
  11. [self setNeedsLayout];
  12. }

最后在TRMusicsTableViewController类中回答三问给表视图加载歌曲数据,并将单元格的行高设置为50,代码如下所示:

  1. -(NSInteger)tableView:(UITableView *)tableView
  2. numberOfRowsInSection:(NSInteger)section
  3. {
  4. return self.musics.count;
  5. }
  6. -(UITableViewCell *)tableView:(UITableView *)tableView
  7. cellForRowAtIndexPath:(NSIndexPath *)indexPath
  8. {
  9. TRMusicCell *cell = [tableView dequeueReusableCellWithIdentifier:musicCellIdentifier forIndexPath:indexPath];
  10. cell.music = self.musics[indexPath.row];
  11. return cell;
  12. }
  13. -(CGFloat)tableView:(UITableView *)tableView
  14. heightForRowAtIndexPath:(NSIndexPath *)indexPath
  15. {
  16. return 50;
  17. }

5.4 完整代码

本案例中,TRAppDelegate.m文件中的完整代码如下所示:

 
  1. #import "TRAppDelegate.h"
  2. #import "TRMusicGroup.h"
  3. #import "TRMusicTableViewController.h"
  4. @implementation TRAppDelegate
  5. -(BOOL)application:(UIApplication *)application
  6. didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  7. {
  8. NSArray *musicGroups = [TRMusicGroup fakeData];
  9. TRMusicGroup *group = musicGroups[0];
  10. UINavigationController *navi = (UINavigationController *)self.window.rootViewController;
  11. TRMusicTableViewController *musicTVC = (TRMusicTableViewController *) navi.topViewController;
  12. musicTVC.musics = group.musics;
  13. return YES;
  14. }
  15. @end

本案例中,TRMusicTableViewController.h文件中的完整代码如下所示:

 
  1. #import <UIKit/UIKit.h>
  2. @interface TRMusicTableViewController : UITableViewController
  3. @property (strong, nonatomic) NSArray *musics;
  4. @end

本案例中,TRMusicCell.h文件中的完整代码如下所示:

 
  1. #import <UIKit/UIKit.h>
  2. #import "TRMusic.h"
  3. @interface TRMusicCell : UITableViewCell
  4. @property (strong, nonatomic) TRMusic *music;
  5. @end

本案例中,TRMusicCell.m文件中的完整代码如下所示:

 
  1. #import "TRMusicCell.h
  2. @interface TRMusicCell ()
  3. @property (weak, nonatomic) IBOutlet UILabel *musicNameLabel;
  4. @property (weak, nonatomic) IBOutlet UILabel *albumAndArtistLabel;
  5. @property (weak, nonatomic) IBOutlet UILabel *durationLabel;
  6. @property (weak, nonatomic) IBOutlet UIImageView *downloadedImageView;
  7. @property (weak, nonatomic) IBOutlet UIImageView *hdImageView;
  8. @end
  9. @implementation TRMusicCell
  10. - (void)setMusic:(TRMusic *)music
  11. {
  12. _music = music;
  13. self.musicNameLabel.text = music.name;
  14. self.albumAndArtistLabel.text = [NSString stringWithFormat:@"%@ - %@", music.album, music.artist];
  15. self.durationLabel.text = [NSString stringWithFormat:@"%d:%02d", (int)music.duration/60, (int)music.duration%60];
  16. self.downloadedImageView.hidden = !music.downloaded;
  17. self.hdImageView.hidden = !music.highQuality;
  18. [self setNeedsLayout];//需要重新布局
  19. }
  20. //当当前视图的大小发生变化时调用
  21. - (void)layoutSubviews
  22. {
  23. [super layoutSubviews];
  24. CGFloat x = self.downloadedImageView.frame.origin.x;
  25. if (self.music.downloaded){
  26. x += 20;
  27. }
  28. if (self.music.highQuality) {
  29. CGRect frame = self.hdImageView.frame;
  30. frame.origin.x = x;
  31. self.hdImageView.frame = frame;
  32. x += 20;
  33. }
  34. CGRect frame = self.albumAndArtistLabel.frame;
  35. frame.origin.x = x;
  36. self.albumAndArtistLabel.frame = frame;
  37. }
  38. @end

本案例中,TRMusic.h文件中的完整代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. @interface TRMusic : NSObject
  3. @property (nonatomic, copy) NSString * name;
  4. @property (nonatomic, copy) NSString * album;
  5. @property (nonatomic, copy) NSString * artist;
  6. @property (nonatomic) NSTimeInterval duration;
  7. @property (nonatomic) BOOL highQuality;
  8. @property (nonatomic) BOOL downloaded;
  9. @end

本案例中,TRMusicGroup.h文件中的完整代码如下所示:

 
  1. #import <Foundation/Foundation.h>
  2. #import "TRMusic.h"
  3. typedef NS_ENUM(NSInteger, TRMusicGroupState) {
  4. TRMusicGroupStateNormal,
  5. TRMusicGroupStateDownloading,
  6. TRMusicGroupStateDownloaded
  7. };
  8. @interface TRMusicGroup : NSObject
  9. @property (nonatomic, copy) NSString * name;
  10. @property (nonatomic, strong) NSArray * musics;
  11. @property (nonatomic) TRMusicGroupState state;
  12. + (NSArray *) fakeData;
  13. @end

本案例中,TRMusicGroup.m文件中的完整代码如下所示:

 
  1. #import "TRMusicGroup.h"
  2. @implementation TRMusicGroup
  3. + (NSArray *) fakeData
  4. {
  5. NSMutableArray * musics = nil;
  6. TRMusic * music = nil;
  7. musics = [NSMutableArray array];
  8. music = [[TRMusic alloc] init];
  9. music.name = @"Burn";
  10. music.album = @"Burn - Single";
  11. music.artist = @"Ellie Goulding";
  12. music.duration = [self durationWithMinutes:3 andSeconds:51];
  13. music.downloaded = YES;
  14. music.highQuality = NO;
  15. [musics addObject:music];
  16. music = [[TRMusic alloc] init];
  17. music.name = @"Summertime Sadness (Cedric Gervais Remix)";
  18. music.album = @"Summertime Sadness (Cedric Gervais Remix) - Single";
  19. music.artist = @"Lana Del Rey";
  20. music.duration = [self durationWithMinutes:6 andSeconds:52];
  21. music.downloaded = YES;
  22. music.highQuality = YES;
  23. [musics addObject:music];
  24. music = [[TRMusic alloc] init];
  25. music.name = @"Spectrum";
  26. music.album = @"Clarity";
  27. music.artist = @"Zedd";
  28. music.duration = [self durationWithMinutes:4 andSeconds:3];
  29. music.downloaded = YES;
  30. music.highQuality = YES;
  31. [musics addObject:music];
  32. music = [[TRMusic alloc] init];
  33. music.name = @"It's Time";
  34. music.album = @"It’s Time";
  35. music.artist = @"Imagine Dragons";
  36. music.duration = [self durationWithMinutes:4 andSeconds:0];
  37. music.downloaded = NO;
  38. music.highQuality = YES;
  39. [musics addObject:music];
  40. music = [[TRMusic alloc] init];
  41. music.name = @"Dancing in The Moonlight";
  42. music.album = @"Dancing In The Moonlight: The Best Of Toploader";
  43. music.artist = @"Toploader";
  44. music.duration = [self durationWithMinutes:3 andSeconds:53];
  45. music.downloaded = YES;
  46. music.highQuality = YES;
  47. [musics addObject:music];
  48. music = [[TRMusic alloc] init];
  49. music.name = @"Thinking About You (feat. Ayah Marar)";
  50. music.album = @"18 Months (Deluxe Edition)";
  51. music.artist = @"Calvin Harris";
  52. music.duration = [self durationWithMinutes:4 andSeconds:8];
  53. music.downloaded = YES;
  54. music.highQuality = YES;
  55. [musics addObject:music];
  56. music = [[TRMusic alloc] init];
  57. music.name = @"You Make Me (feat. Salem Al Fakir)";
  58. music.album = @"True";
  59. music.artist = @"Avicii";
  60. music.duration = [self durationWithMinutes:3 andSeconds:51];
  61. music.downloaded = YES;
  62. music.highQuality = NO;
  63. [musics addObject:music];
  64. music = [[TRMusic alloc] init];
  65. music.name = @"Safe and Sound";
  66. music.album = @"Capital Cities EP";
  67. music.artist = @"Capital Cities";
  68. music.duration = [self durationWithMinutes:3 andSeconds:51];
  69. music.downloaded = YES;
  70. music.highQuality = NO;
  71. [musics addObject:music];
  72. music = [[TRMusic alloc] init];
  73. music.name = @"Reaching Out";
  74. music.album = @"Welcome Reality (Deluxe Version)";
  75. music.artist = @"nero";
  76. music.duration = [self durationWithMinutes:3 andSeconds:51];
  77. music.downloaded = YES;
  78. music.highQuality = NO;
  79. [musics addObject:music];
  80. music = [[TRMusic alloc] init];
  81. music.name = @"Recover";
  82. music.album = @"Recover - EP";
  83. music.artist = @"CHVRCHES";
  84. music.duration = [self durationWithMinutes:3 andSeconds:51];
  85. music.downloaded = YES;
  86. music.highQuality = NO;
  87. [musics addObject:music];
  88. music = [[TRMusic alloc] init];
  89. music.name = @"Hold On, We're Going Home (feat. Majid Jordan)";
  90. music.album = @"Hold On, We're Going Home (feat. Majid Jordan) - Single";
  91. music.artist = @"Drake";
  92. music.duration = [self durationWithMinutes:3 andSeconds:51];
  93. music.downloaded = YES;
  94. music.highQuality = NO;
  95. [musics addObject:music];
  96. music = [[TRMusic alloc] init];
  97. music.name = @"The Mother We Share";
  98. music.album = @"The Mother We Share - Single";
  99. music.artist = @"CHVRCHES";
  100. music.duration = [self durationWithMinutes:3 andSeconds:51];
  101. music.downloaded = YES;
  102. music.highQuality = NO;
  103. [musics addObject:music];
  104. music = [[TRMusic alloc] init];
  105. music.name = @"Promises";
  106. music.album = @"nero";
  107. music.artist = @"Promises - EP";
  108. music.duration = [self durationWithMinutes:3 andSeconds:51];
  109. music.downloaded = YES;
  110. music.highQuality = NO;
  111. [musics addObject:music];
  112. music = [[TRMusic alloc] init];
  113. music.name = @"Alone Together";
  114. music.album = @"Save Rock and Roll";
  115. music.artist = @"Fall Out Boy";
  116. music.duration = [self durationWithMinutes:3 andSeconds:51];
  117. music.downloaded = YES;
  118. music.highQuality = NO;
  119. [musics addObject:music];
  120. music = [[TRMusic alloc] init];
  121. music.name = @"Reload (Radio Edit)";
  122. music.album = @"Reload (Radio Edit) - Single";
  123. music.artist = @"Sebastian Ingrosso";
  124. music.duration = [self durationWithMinutes:3 andSeconds:51];
  125. music.downloaded = YES;
  126. music.highQuality = NO;
  127. [musics addObject:music];
  128. music = [[TRMusic alloc] init];
  129. music.name = @"I Love It (feat. Charli XCX)";
  130. music.album = @"Iconic";
  131. music.artist = @"Icona Pop";
  132. music.duration = [self durationWithMinutes:3 andSeconds:51];
  133. music.downloaded = YES;
  134. music.highQuality = NO;
  135. [musics addObject:music];
  136. music = [[TRMusic alloc] init];
  137. music.name = @"Feel the Love";
  138. music.album = @"Feel the Love (feat. John Newman) [Remixes] - EP";
  139. music.artist = @"Rudimental";
  140. music.duration = [self durationWithMinutes:3 andSeconds:51];
  141. music.downloaded = YES;
  142. music.highQuality = NO;
  143. [musics addObject:music];
  144. music = [[TRMusic alloc] init];
  145. music.name = @"Goin' Crazy (feat. Robbie Williams)";
  146. music.album = @"Goin' Crazy (feat. Robbie Williams) - Single";
  147. music.artist = @"Dizzee Rascal";
  148. music.duration = [self durationWithMinutes:3 andSeconds:51];
  149. music.downloaded = YES;
  150. music.highQuality = NO;
  151. [musics addObject:music];
  152. music = [[TRMusic alloc] init];
  153. music.name = @"Still Into You";
  154. music.album = @"Paramore";
  155. music.artist = @"Paramore";
  156. music.duration = [self durationWithMinutes:3 andSeconds:51];
  157. music.downloaded = YES;
  158. music.highQuality = NO;
  159. [musics addObject:music];
  160. music = [[TRMusic alloc] init];
  161. music.name = @"Heart Attack";
  162. music.album = @"Demi";
  163. music.artist = @"Demi Lovato";
  164. music.duration = [self durationWithMinutes:3 andSeconds:51];
  165. music.downloaded = YES;
  166. music.highQuality = NO;
  167. [musics addObject:music];
  168. music = [[TRMusic alloc] init];
  169. music.name = @"Explosions";
  170. music.album = @"Halcyon (Deluxe Edition)";
  171. music.artist = @"Ellie Goulding";
  172. music.duration = [self durationWithMinutes:3 andSeconds:51];
  173. music.downloaded = YES;
  174. music.highQuality = NO;
  175. [musics addObject:music];
  176. music = [[TRMusic alloc] init];
  177. music.name = @"I Need Your Love (feat. Ellie Goulding)";
  178. music.album = @"I Need Your Love";
  179. music.artist = @"Calvin Harris";
  180. music.duration = [self durationWithMinutes:3 andSeconds:51];
  181. music.downloaded = YES;
  182. music.highQuality = NO;
  183. [musics addObject:music];
  184. music = [[TRMusic alloc] init];
  185. music.name = @"Starry Eyed";
  186. music.album = @"Bright Lights";
  187. music.artist = @"Ellie Goulding";
  188. music.duration = [self durationWithMinutes:3 andSeconds:51];
  189. music.downloaded = YES;
  190. music.highQuality = NO;
  191. [musics addObject:music];
  192. music = [[TRMusic alloc] init];
  193. music.name = @"Lights (Single Version)";
  194. music.album = @"Bright Lights";
  195. music.artist = @"Ellie Goulding";
  196. music.duration = [self durationWithMinutes:3 andSeconds:51];
  197. music.downloaded = YES;
  198. music.highQuality = NO;
  199. [musics addObject:music];
  200. music = [[TRMusic alloc] init];
  201. music.name = @"Who's That Chick?";
  202. music.album = @"Who's That Chick - Single";
  203. music.artist = @"David Guetta";
  204. music.duration = [self durationWithMinutes:2 andSeconds:47];
  205. music.downloaded = YES;
  206. music.highQuality = NO;
  207. [musics addObject:music];
  208. TRMusicGroup * g1 = [[TRMusicGroup alloc] init];
  209. g1.name = @"国外单曲";
  210. g1.musics = [musics copy];
  211. g1.state = TRMusicGroupStateDownloaded;
  212. musics = [NSMutableArray array];
  213. music = [[TRMusic alloc] init];
  214. music.name = @"致青春";
  215. music.album = @"致青春";
  216. music.artist = @"王菲";
  217. music.duration = [self durationWithMinutes:3 andSeconds:18];
  218. music.downloaded = NO;
  219. music.highQuality = NO;
  220. [musics addObject:music];
  221. music = [[TRMusic alloc] init];
  222. music.name = @"好汉歌";
  223. music.album = @"六十年代生人";
  224. music.artist = @"刘欢";
  225. music.duration = [self durationWithMinutes:3 andSeconds:41];
  226. music.downloaded = NO;
  227. music.highQuality = YES;
  228. [musics addObject:music];
  229. music = [[TRMusic alloc] init];
  230. music.name = @"忐忑";
  231. music.album = @"自由鸟";
  232. music.artist = @"龚琳娜";
  233. music.duration = [self durationWithMinutes:4 andSeconds:03];
  234. music.downloaded = NO;
  235. music.highQuality = YES;
  236. [musics addObject:music];
  237. music = [[TRMusic alloc] init];
  238. music.name = @"爱情买卖";
  239. music.album = @"我们的爱我不放手";
  240. music.artist = @"慕容晓晓";
  241. music.duration = [self durationWithMinutes:3 andSeconds:31];
  242. music.downloaded = NO;
  243. music.highQuality = YES;
  244. [musics addObject:music];
  245. music = [[TRMusic alloc] init];
  246. music.name = @"法海你不懂爱";
  247. music.album = @"法海你不懂爱 - 单曲";
  248. music.artist = @"龚琳娜";
  249. music.duration = [self durationWithMinutes:3 andSeconds:33];
  250. music.downloaded = NO;
  251. music.highQuality = NO;
  252. [musics addObject:music];
  253. music = [[TRMusic alloc] init];
  254. music.name = @"最炫民族风";
  255. music.album = @"我们的爱我不放手";
  256. music.artist = @"凤凰传奇";
  257. music.duration = [self durationWithMinutes:4 andSeconds:46];
  258. music.downloaded = NO;
  259. music.highQuality = YES;
  260. [musics addObject:music];
  261. music = [[TRMusic alloc] init];
  262. music.name = @"金箍棒";
  263. music.album = @"金箍棒 - 单曲";
  264. music.artist = @"龚琳娜";
  265. music.duration = [self durationWithMinutes:2 andSeconds:52];
  266. music.downloaded = NO;
  267. music.highQuality = NO;
  268. [musics addObject:music];
  269. TRMusicGroup * g2 = [[TRMusicGroup alloc] init];
  270. g2.name = @"国内神曲";
  271. g2.musics = [musics copy];
  272. g2.state = TRMusicGroupStateNormal;
  273. TRMusicGroup * g3 = [[TRMusicGroup alloc] init];
  274. g3.name = @"Calvin Harris 专辑";
  275. g3.musics = @[];
  276. g3.state = TRMusicGroupStateNormal;
  277. TRMusicGroup * g4 = [[TRMusicGroup alloc] init];
  278. g4.name = @"Ellie Gounding 专辑";
  279. g4.musics = @[];
  280. g4.state = TRMusicGroupStateNormal;
  281. return @[g1, g2, g3, g4];
  282. }
  283. + (NSTimeInterval) durationWithMinutes:(int)minutes andSeconds:(int)seconds
  284. {
  285. return minutes * 60 + seconds;
  286. }
  287. @end

触控(Touch) 、 布局(Layout)的更多相关文章

  1. 触控(Touch)

    1 使用触控实现一个简易的画板 1.1 问题 触控(Touch)是一个UITouch类型的对象,当用户触摸了屏幕上的视图时自动被创建,通常使用触控实现绘图.涂鸦.手写等功能.本案例使用触控实现一个简易 ...

  2. sencha touch 入门系列 (九) sencha touch 布局layout

    布局用来描述你应用程序中组件的大小和位置,在sencha touch中,为我们提供了下面几种布局: 1.HBox: HBox及horizontal box布局,我们这里将其称为水平布局,下面是一段演示 ...

  3. Duilib源码分析(五)UI布局—Layout与各子控件

    接下来,继续分析duilib之UI布局Layout,目前提供的布局有:VerticalLayout.HorizontalLayout.TileLayout.TabLayout.ChildLayout分 ...

  4. 移动端H5混合开发,Touch触控,拖拽,长按, 滑屏 实现方案

    概述 近期由于产品快速原型开发的需要,不想用原声的方式开发App两端一起搞时间来不及,目前产品处于大量上feature的阶段,采用混合开发是最合适的选择,所以花了3天的时间研究怎么去实现移动端,拖拽, ...

  5. cocos creator Touch事件应用(触控选择多个子节点)

    最近参与了cocos creator的研究,开发小游戏,结果被一个事件坑得不行不行的.现在终于解决了,分享给大家. 原理 1.触控事件是针对节点的 2.触控事件的冒泡,是一级一级往上冒泡,中间可以阻止 ...

  6. Touch Bar 废物利用系列 | 在触控栏上显示 Dock 应用图标

    都说 Intel 第八代 CPU 对比上代是牙膏不小心挤多了,而配备第八代 CPU 的 MacBook Pro,只有 Touch Bar 版本,虽然贵了一点,但就一个字 -- 买! 收到电脑后,兴冲冲 ...

  7. 【朝花夕拾】Android自定义View篇之(八)多点触控(上)MotionEvent简介

    前言 在前面的文章中,介绍了不少触摸相关的知识,但都是基于单点触控的,即一次只用一根手指.但是在实际使用App中,常常是多根手指同时操作,这就需要用到多点触控相关的知识了.多点触控是在Android2 ...

  8. Android多点触控技术实战,自由地对图片进行缩放和移动

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11100327 在上一篇文章中我带着大家一起实现了Android瀑布流照片墙的效果, ...

  9. MultiTouch————多点触控,伸缩图片,变换图片位置

    前言:当今的手机都支持多点触控功能(可以进行图片伸缩,变换位置),但是我们程序员要怎样结合硬件去实现这个功能呢? 跟随我一起,来学习这个功能 国际惯例:先上DEMO免费下载地址:http://down ...

随机推荐

  1. SQL Server数据库(作业讲解和复习)

    --第一题 查询Student表中的所有记录的Sname.Ssex和Class列.select Sname,Ssex,Class from student --第二题 查询教师所有的单位即不重复的De ...

  2. Java 正则表达式 向前、向后匹配

    //向后匹配 String a = "I paid $90 for 10 oranges, 12 pears and 8 apples. I saved $5 on "; Patt ...

  3. 告别node-forever,拥抱PM2

    告别node-forever,拥抱PM2 返回原文英文原文:Goodbye node-forever,hello PM2 devo.ps团队对JavaScript的迷恋已经不是什么秘密了;node.j ...

  4. 我的R代码备份

    1 #f1=scan(file="f1.txt");  2 #f2=scan(file="f2.txt");  3 f=scan(file="5.2_ ...

  5. 转:Nginx+Apache环境的安装与配置

    转:http://www.server110.com/nginx/201404/8817.html 我们依然尽可能采用yum来安装我们需要的软件,由系统官方维护的软件,其安全性和稳定性都值得信赖,并且 ...

  6. js中Array自定义contains, indexOf, delete方法.

    Array.prototype.contains = function (elem) { for (var i = 0; i < this.length; i++) { if (this[i] ...

  7. jquery返回上一页面

    window.location.href=document.referrer;   返回然后刷新 window.history.back(-1);  返回不刷新

  8. ICTCLA中科院分词工具用法(java)

    摘要:为解决中文搜索的问题,最开始使用PHP版开源的SCWS,但是处理人名和地名时,会出现截断人名地名出现错误.开始使用NLPIR分词,在分词准确性上效果要比SCWS好.本文介绍如何在windows系 ...

  9. Codeforces Round #326 (Div. 2)-Duff and Meat

    题意: Duff每天要吃ai千克肉,这天肉的价格为pi(这天可以买好多好多肉),现在给你一个数值n为Duff吃肉的天数,求出用最少的钱满足Duff的条件. 思路: 只要判断相邻两天中,今天的总花费 = ...

  10. 【转发】RedHat Enterprise Linux 6.4 使用 Centos 6 的yum源问题

    作为一名新手,学习Linux已经一个月了,其间遇到了不少问题,而今天笔者遇到的问题是 #yum install pam-devel #This system is not registered to ...