针对IOS6提出的全新特性UICollectionView做了一个实际的使用,有很多地方还是很有意义的,定制化貌似更加的灵活了,这样对于大量的自定义来说更是“万事俱备,东风已来”矣。在Apple Developer 中心也有Demo,那个Demo也是很有意思的,文章最后会给出下载地址。
一、战果展示,呵呵~~
实现了一个圆形的UICollectionView的使用,当触摸非圆周的部分时,Cell会增加,这里注意每个小图片就是一个cell;当触摸圆周上的cell,也就是小图片的时候,对应的cell就会消除。至于中间那个,嘿嘿~~是实现的一个gif效果显示。这里分享一个IOS设备上实现gif效果图的图片获取方法。将一张gif图片在MAC机上使用系统自带的“预览”打开,就可以看到一张一张的图片了。然后按照顺序“另存为”即可拿到顺序的图片了。
二、代码分析
1.1 代理方法介绍(AppDelegate)
在AppDelegate里面,方法didFinishLaunchingWithOption中,创建ViewController,这个Controller是继承自UICollectionViewController的,并且初始化controller的使用需要制定Controller的Layout,这个Layout就是制定CollectionView里面的cells和supplementary views的。
样例代码:
1. #import "AppDelegate.h"
2.
3. #import "ViewController.h"
4. #import "CircleLayout.h"
5.
6. @implementation AppDelegate
7.
8. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
9. {
10. self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
11. // Override point for customization after application launch.
12. self.viewController = [[ViewController alloc] initWithCollectionViewLayout:[[CircleLayout alloc] init]];
13. self.window.rootViewController = self.viewController;
14. [self.window makeKeyAndVisible];
15. return YES;
16. }
1.2 自定义Layout类介绍(CircleLayout)
在上面代码中,可以看到引入了一个类CircleLayout.h ,这个类的作用就是指定页面的Layout样式的。从结果图上可以看到,这个类里面至少要实现cell的样式、collectionView的样式。要实现的东西不少~~~
CircleLayout类是继承自UICollectionViewLayout的,而UICollectionViewLayout类是一个抽象基类,通过继承它可以生成collectionView的Layout信息。而Layout的作用就是决定CollectionView中的Cell、supplementary view、decoration view的位置的。在使用UICollectionViewLayout的时候,必须谨记“先子类化,后使用” !
1.2.1 子类化
在子类化UICollectionViewLayout的时候,需要注意:
aa Layout只负责布局样式,而不负责创建view。(view的创建是通过代理方法 datasource来实现的)
bb Layout对象中定义了view的位置以及view大小size的信息
1.2.2 UICollectionView 的三要素介绍
Cells:Layout就像一个管理者,而cell就是被管理者,每一个cell代表了collectionview中的一个item,一个collectionview可以放在一个section中,也可以放在整个UICollectionview中。使用和位置都是由Layout对象定义的。
Supplementary Views:纯属显示的一个要素,不能被用户选择,而且还是可有可无的。只要你想为Section或者整个collection view 添加页眉和页脚,它就是了。
Decoration Views:一个装饰品,不可被用户选择,类似于Supplementary View,使用和位置都是由Layout定义的。可有可无。
1.2.3 需要重载的方法介绍
每一个管理者(Layout对象)都有自己的一套方法,来管理手下的虾兵小将:
1. collectionViewContentSize
2. shouldInvalidateLayoutForBoundsChange:
3. layoutAttributesForElementsInRect:
4. layoutAttributesForItemAtIndexPath:
5. layoutAttributesForSupplementaryViewOfKind:atIndexPath: (如果layout 支持 supplementary views)
6.layoutAttributesForDecorationViewWithReuseIdentifier:atIndexPath: (如果layout 支持 decoration views)
上述方法的具体含义和作用,可参考SDK
1.2.4 折腾“插入”和"删除 "
当collection view 中的数据发生了变化,例如其中的item有了变化,collection view 都需要重新检索相应的Layout信息,来得到新的显示。这样collection view 就有了自己的一套检索的方法,你只需要进行重载就可以了。
• initialLayoutAttributesForInsertedItemAtIndexPath:
• initialLayoutAttributesForInsertedSupplementaryElementOfKind:atIndexPath:
• finalLayoutAttributesForDeletedItemAtIndexPath:
但是这里只需要进行简单的实现,所以只需要重载一下两个方法:
- initialLayoutAttributesForInsertedItemAtIndexPath:
- OK,这就是自定义的CircleLayout类中需要注意的。下来上code: CircleLayout.h 文件:
• 1. #import <UIKit/UIKit.h>
2.
3. @interface CircleLayout : UICollectionViewLayout
4.
5. //定义圆的圆心、半径,以及cell的个数
6.
7. @property (nonatomic,assign) CGPoint center;
8. @property (nonatomic,assign) CGFloat radius;
9. @property (nonatomic,assign) NSInteger cellCount;
10.
11. @end
- CircleLayout.m文件:
1. #import "CircleLayout.h"
2.
3. //定义item的大小
4. #define ITEM_SIZE 70
5.
6. @implementation CircleLayout
7.
8. //为创建Circle做准备
9. - (void)prepareLayout{
10. [super prepareLayout];
11.
12. CGSize size = self.collectionView.frame.size;
13. _cellCount = [[self collectionView] numberOfItemsInSection:0];
14. _center = CGPointMake(size.width / 2.0, size.height / 2.0);
15. _radius = MIN(size.width, size.height) / 2.5;
16. }
17.
18. //设置collectionViewContentsize
19. - (CGSize) collectionViewContentSize{
20. return self.collectionView.frame.size;
21. }
22.
23. //设置UICollectionViewLayoutAttributes
24. - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
25. UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
26. attributes.size = CGSizeMake(ITEM_SIZE, ITEM_SIZE);
27. attributes.center = CGPointMake(_center.x + _radius * cosf(2 * indexPath.item * M_PI / _cellCount),
28. _center.y + _radius * sinf(2 * indexPath.item * M_PI / _cellCount));
29.
30. return attributes;
31. }
32.
33. //设置layoutAttributesForElementsInRect
34. - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{
35. NSMutableArray *attributes = [NSMutableArray array];
36. for(NSInteger i = 0; i < self.cellCount; i++){
37. NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
38. [attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
39. }
40. return attributes;
41. }
42.
43. #pragma mark --
44. #pragma mark Layout init & final
45.
46. //复写initialLayoutAttributesForInsertedItemAtIndexPath
47. - (UICollectionViewLayoutAttributes *)initialLayoutAttributesForInsertedItemAtIndexPath:(NSIndexPath *)itemIndexPath
48. {
49. UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
50. attributes.alpha = 0.0;
51. attributes.center = CGPointMake(_center.x, _center.y);
52. return attributes;
53. }
54.
55. //复写finalLayoutAttributesForDeletedItemAtIndexPath
56.
57. - (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDeletedItemAtIndexPath:(NSIndexPath *)itemIndexPath
58. {
59. UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
60. attributes.alpha = 0.0;
61. attributes.center = CGPointMake(_center.x, _center.y);
62. attributes.transform3D = CATransform3DMakeScale(0.1, 0.1, 1.0);
63. return attributes;
64. }
65. @end
- 1.3 自定义Cell
关于UITableViewCell的自定义,估计大多数人都会不止一种的自定义方法吧,UICollectionViewCell也可以定制,这样就极大的方便了那些需要震撼性UI的App开发者的使用了。UICollectionViewCell的主要功能就是管理collectionview中的每一个item了,注意只是当item在屏幕的可视范围的时候,OK,那么自定义的这个Cell就直接继承自UICollectionViewCell类,在这个自定义的Cell中需要一个图像容器UIImageView来存放每一个item上的图片。
1. #import <UIKit/UIKit.h>
2.
3. @interface CircleCell : UICollectionViewCell
4.
5. @property (nonatomic,strong) UIImageView *imageView;
6.
7. @end
1. #import "CircleCell.h"
2. #import <QuartzCore/QuartzCore.h>
3.
4. @implementation CircleCell
5.
6. @synthesize imageView;
7.
8. - (id)initWithFrame:(CGRect)frame
9. {
10. self = [super initWithFrame:frame];
11. if (self) {
12. // Initialization code
13. self.contentView.layer.cornerRadius = 10.0f;
14. self.contentView.frame = CGRectMake(0, 0, 75, 75);
15. self.contentView.layer.borderWidth = 1.0f;
16. self.contentView.layer.borderColor = [UIColor whiteColor].CGColor;
17. self.contentView.backgroundColor = [UIColor underPageBackgroundColor];
18.
19. "1_120103225810_1.jpeg"]];
20. self.imageView.layer.masksToBounds = YES;
21. self.imageView.layer.cornerRadius = 10.0f;
22. self.imageView.frame = self.contentView.frame;
23. [self.contentView addSubview:self.imageView];
24.
25. }
26. return self;
27. }
28. @end
- 完成之后,就完成了大部分的code准备工作了。接下来就是要在开始那个ViewController类中进行调用使用了。
三、最终的code
首先要实现UICollectionView的两个代理方法:delegate & dataSource。并且要给collectionView 添加Tap 手势哦,这样才能让用户在触摸的时候有所交互。
直接上code吧。HOHO~~
ViewController.h 文件:
1. #import <UIKit/UIKit.h>
2.
3. @interface ViewController : UICollectionViewController
4.
5. @property (nonatomic,assign)NSInteger cellCount;
6.
7. @end
- ViewController.m 文件:
1. #import "ViewController.h"
2. #import "GifLayoutView.h"
3. #import "CircleCell.h"
4.
5. @interface ViewController ()
6.
7. @end
8.
9. @implementation ViewController
10.
11. - (void)viewDidLoad
12. {
13. [super viewDidLoad];
14. // Do any additional setup after loading the view, typically from a nib.
15.
16. //添加背景gif显示图View
17. GifLayoutView *gifView = [[GifLayoutView alloc]initWithFrame:CGRectMake(0, 0, 350, 350)];
18. gifView.center = self.collectionView.center;
19. [self.collectionView addSubview:gifView];
20.
21. //为collectionView添加tapGesture,并注册。
22. self.cellCount = 20;
23. UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
24. [self.collectionView addGestureRecognizer:tapGesture];
25. class] forCellWithReuseIdentifier:@"Circle_Cell"];
26. [self.collectionView reloadData];
27. self.collectionView.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
28.
29. }
30.
31. //设置numberOfItemsInSection
32. - (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section;
33. {
34. return self.cellCount;
35. }
36.
37. //复用Cell
38. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
39. {
40. "Circle_Cell" forIndexPath:indexPath];
41. return cell;
42. }
43.
44. //手势的相应事件
45. - (void)handleTapGesture:(UITapGestureRecognizer *)sender {
46.
47. if (sender.state == UIGestureRecognizerStateEnded)
48. {
49. CGPoint initialPinchPoint = [sender locationInView:self.collectionView];
50. NSIndexPath* tappedCellPath = [self.collectionView indexPathForItemAtPoint:initialPinchPoint];
51. if (tappedCellPath!=nil)
52. {
53. self.cellCount = self.cellCount - 1;
54. [self.collectionView performBatchUpdates:^{
55. [self.collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObject:tappedCellPath]];
56.
57. } completion:nil];
58. }
59. else
60. {
61. self.cellCount = self.cellCount + 1;
62. [self.collectionView performBatchUpdates:^{
63. [self.collectionView insertItemsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForItem:0 inSection:0]]];
64. } completion:nil];
65. }
66. }
67. }
68. - (void)didReceiveMemoryWarning
69. {
70. [super didReceiveMemoryWarning];
71. // Dispose of any resources that can be recreated.
72. }
73.
74. @end