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

转载于:https://www.cnblogs.com/hytx/p/5049478.html

触控(Touch) 、 布局(Layout)相关推荐

  1. 基于stm32智能风扇_意法半导体和Fieldscale为基于STM32的智能设备带来简单直观的触控体验...

    "意法半导体与ST授权合作伙伴.仿真软件提供商Fieldscale合作,简化基于STM32微控制器(MCU)的智能设备的触控用户界面开发过程. " • Fieldscale SEN ...

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

    简评: 这是我见过的最有用的 TouchBar 应用,感谢@Aceyclee 分享 都说 Intel 第八代 CPU 对比上代是牙膏不小心挤多了,而配备第八代 CPU 的 MacBook Pro,只有 ...

  3. php 控件 手机触控,html5手机触屏touch事件的详细介绍

    HTML5中新添加了很多事件,但是由于他们的兼容问题不是很理想,应用实战性不是太强,所以在这里基本省略,咱们只分享应用广泛兼容不错的事件,日后随着兼容情况提升以后再陆续添加分享. 今天为大家介绍的事件 ...

  4. 修复MacBook Touch Bar(触控栏)无法正常工作的方法

    MacBook电脑也是苹果用户喜爱的产品之一.苹果在MacBook上推出的Touch Bar(触控条)也是打开了人机交互新的领域. 但是,在网络上.最近老是有用户反馈Touch Bar卡顿或者不流畅等 ...

  5. iOS9 3D Touch 标签菜单 peek and pop force 压力触控 功能开发高级版教程

    iOS9 3D Touch 标签菜单 peek and pop  force 压力触控 功能开发高级版教程 github地址: https://github.com/wyk125/3DTouchDem ...

  6. 三维触控测试软件,解读苹果3D touch三维触控技术

    苹果在iphone6s上发布了3d touch三维触控的新功能.3d touch能够让iphone6s识别超过寻常平面的二维触控操作,用户可以通过手机按压的力度以触发不同的操作.下面我们来详细了解一下 ...

  7. Unity手指触控之Touch结构体

    一.Touch结构体介绍 1.Touch是一个结构体,每当发生一次触摸,系统生成一个Touch类型的变量,存储本次触摸的相关信息:如果发生多点触控,那么系统就会生成多个Touch类型的变量. 2.To ...

  8. android app防止锁屏_触控禁止!Touch Protector 锁定屏幕触控功能,避免意外操作(Android)...

    「Touch Protector」是一款可以关闭手机萤幕触控功能的App,启动锁定功能后,萤幕仍可继续显示原本的画面,但完全不可触控操作任何功能,连同下方的导航栏与上方的通知栏会都一并上锁,适用于任何 ...

  9. macbookair有没有touchbar_全新MacBook Pro体验评测:Touch Bar触控条到底怎么样?

    对于沉寂的PC行业来说,本周微软和苹果的两场发布会带来不小的谈资:尤其是微软"意外"发布了一款一体机Surface Studio:苹果则"不出所料"的升级了Ma ...

最新文章

  1. python 语义网络_专家鉴定这是2019最顶级的python框架,没有之一
  2. 二分查找对应的二叉树的成功和失败ASL
  3. ios13文件连接服务器教程,iOS 13/iPad OS迈向生产力的一大步,SMB文件共享视频图文教程...
  4. 使用QT Creator开发C++程序
  5. [From 10.1~10.5] 对象和集合初始化器(C#语法糖系列)
  6. tcode search_sap_menu 根据关键字搜索SAP menu
  7. 2016年10月30日表单标签与样式表分类和选择器
  8. Cortex-M3寄存器组
  9. 关于WPF装饰器的笔记
  10. C/C++线程与多线程工作笔记003---C++指针引用和解引用
  11. FFmpeg(六) 播放视频之GLSurfaceView显示RGB数据
  12. LoadRunner踩坑记录:服务器“127.0.0.1”在尝试协商 SSL 会话时关闭连接
  13. Eclipse中Tab的配置(设置为按一下Tab键,效果是按4次空格,而不是4个空格的缩进)
  14. 排序算法之——插入排序分析
  15. android 请求https请求,Android 实现 HttpClient 请求Https
  16. 计算机播放音乐自录,怎么录制电脑上正在播放的视频音频
  17. 台式计算机怎样能搜无线连接,台式电脑如何连接无线网络
  18. 【新年新气象_新年CSDN第一篇】斯特林数简介及应用
  19. java txt转pdf乱码,openoffice将txt文本转pdf中文乱码
  20. 防住CV中这颗“不定时炸弹”,有哪些捷径?丨独家公开课实录(4)

热门文章

  1. java某市出租车_智慧职教mooc的APPJavaEE企业级网站开发章节测验答案
  2. case when 子查询_Oracle数据库-单表查询
  3. linux停止客户端,linux – 从客户端打印motd停止ssh登录?
  4. php-cgi.sock 权限,php-fpm sock文件权限设置
  5. java sha1加密ascii码_请问下面java的Sha1加密在c#中对应要怎么写?
  6. 用法与区别_指示代词this, that, these, those的区别和用法
  7. 中医大计算机应用基础考试题6,中医大 计算机应用基础 复习题 参考资料.docx
  8. 使用Python,OpenCV进行图像哈希
  9. 在Win10下如何实现VS下工程代码的开机自启功能
  10. 在Python上使用OpenCV检测和跟踪行人