使用UICollectionView
使用UICollectionView的流程:
1. 设定一个UICollectionViewFlowLayout
2. 使用这个设定的UICollectionViewFlowLayout来初始化UICollectionView
3. 设置代理对象
4. 继承UICollectionViewCell设定重用的cell
源码:
LargeUICollectionViewFlowLayout.h + LargeUICollectionViewFlowLayout.m
#import <UIKit/UIKit.h>
@interface LargeUICollectionViewFlowLayout : UICollectionViewFlowLayout
@end
#import "LargeUICollectionViewFlowLayout.h"
@implementation LargeUICollectionViewFlowLayout
- (instancetype)init
{
self = [super init];
if (self)
{
self.itemSize = CGSizeMake(70, 70);
self.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);
self.minimumInteritemSpacing = 40.0f;
self.minimumLineSpacing = 5.0f;
}
return self;
}
@end
ShowCollectionViewCell.h + ShowCollectionViewCell.m
#import <UIKit/UIKit.h>
@interface ShowCollectionViewCell : UICollectionViewCell
@end
#import "ShowCollectionViewCell.h"
@implementation ShowCollectionViewCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
self.backgroundColor = [UIColor redColor];
}
return self;
}
@end
RootViewController.h + RootViewController.m
#import <UIKit/UIKit.h>
@interface RootViewController : UIViewController
@end
#import "RootViewController.h"
#import "ShowCollectionViewCell.h"
#import "LargeUICollectionViewFlowLayout.h"
static NSString *identify = @"ItemIdentifier";
@interface RootViewController ()<UICollectionViewDelegate, UICollectionViewDataSource>
@property (nonatomic, strong) UICollectionView *collectionView;
@end
@implementation RootViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 初始化UICollectionView并指定一个UICollectionViewFlowLayout
self.collectionView = \
[[UICollectionView alloc] initWithFrame:self.view.bounds
collectionViewLayout:[LargeUICollectionViewFlowLayout new]];
// 给UICollectionViewCell注册重用标示(collectionView会自动给我们创建重用的cell对象)
[self.collectionView registerClass:[ShowCollectionViewCell class]
forCellWithReuseIdentifier:@"ItemIdentifier"];
// 设置代理对象
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
// 将UICollectionView添加进父视图
[self.view addSubview:_collectionView];
}
-(NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section
{
return 100;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
ShowCollectionViewCell *cell = \
[collectionView dequeueReusableCellWithReuseIdentifier:@"ItemIdentifier"
forIndexPath:indexPath];
return cell;
}
@end
运行后效果如下:
很重要的参数如下所示:
在ShowCollectionViewCell.m中执行打印操作:
打印信息如下:
2014-05-19 16:52:58.873 UICollectionView[3077:60b] {{0, 0}, {70, 70}} A
2014-05-19 16:52:58.875 UICollectionView[3077:60b] {{125, 0}, {70, 70}} B
2014-05-19 16:52:58.875 UICollectionView[3077:60b] {{250, 0}, {70, 70}} C
2014-05-19 16:52:58.875 UICollectionView[3077:60b] {{0, 75}, {70, 70}} D
2014-05-19 16:52:58.876 UICollectionView[3077:60b] {{125, 75}, {70, 70}}
2014-05-19 16:52:58.876 UICollectionView[3077:60b] {{250, 75}, {70, 70}}
2014-05-19 16:52:58.876 UICollectionView[3077:60b] {{0, 150}, {70, 70}}
2014-05-19 16:52:58.877 UICollectionView[3077:60b] {{125, 150}, {70, 70}}
2014-05-19 16:52:58.877 UICollectionView[3077:60b] {{250, 150}, {70, 70}}
2014-05-19 16:52:58.877 UICollectionView[3077:60b] {{0, 225}, {70, 70}}
2014-05-19 16:52:58.878 UICollectionView[3077:60b] {{125, 225}, {70, 70}}
2014-05-19 16:52:58.878 UICollectionView[3077:60b] {{250, 225}, {70, 70}}
2014-05-19 16:52:58.878 UICollectionView[3077:60b] {{0, 300}, {70, 70}}
2014-05-19 16:52:58.879 UICollectionView[3077:60b] {{125, 300}, {70, 70}}
2014-05-19 16:52:58.879 UICollectionView[3077:60b] {{250, 300}, {70, 70}}
2014-05-19 16:52:58.879 UICollectionView[3077:60b] {{0, 375}, {70, 70}}
2014-05-19 16:52:58.880 UICollectionView[3077:60b] {{125, 375}, {70, 70}}
2014-05-19 16:52:58.901 UICollectionView[3077:60b] {{250, 375}, {70, 70}}
2014-05-19 16:52:58.901 UICollectionView[3077:60b] {{0, 450}, {70, 70}}
2014-05-19 16:52:58.902 UICollectionView[3077:60b] {{125, 450}, {70, 70}}
2014-05-19 16:52:58.902 UICollectionView[3077:60b] {{250, 450}, {70, 70}}
2014-05-19 16:52:58.902 UICollectionView[3077:60b] {{0, 525}, {70, 70}}
2014-05-19 16:52:58.903 UICollectionView[3077:60b] {{125, 525}, {70, 70}}
2014-05-19 16:52:58.903 UICollectionView[3077:60b] {{250, 525}, {70, 70}}
2014-05-19 16:53:24.995 UICollectionView[3077:60b] {{0, 600}, {70, 70}}
2014-05-19 16:53:24.996 UICollectionView[3077:60b] {{125, 600}, {70, 70}}
2014-05-19 16:53:24.996 UICollectionView[3077:60b] {{250, 600}, {70, 70}}
分析上述打印信息A,B不难发现:125 - 70 = 55 > 40,所以,minimumInteritemSpacing只是单元格间的最小间距而已.
分析A,D发现,75 - 70 = 5,与minimumLineSpacing设定一致,因为我们是垂直滚动,所以纵向方向的间距是一致的.
知道这些,我们来实现网络请求照片墙的效果.
修改LargeUICollectionViewFlowLayout中的代码如下:
self.itemSize = CGSizeMake(100, 150); // 单元格尺寸
self.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0); // 单元格边缘
self.minimumInteritemSpacing = 10.0f; // 横排单元格最小间隔
self.minimumLineSpacing = 10.0f; // 单元格最小行间距
修改ShowCollectionViewCell.h + ShowCollectionViewCell.m
#import <UIKit/UIKit.h>
@interface ShowCollectionViewCell : UICollectionViewCell
@property (nonatomic, strong) UIImageView *showImageView;
@end
#import "ShowCollectionViewCell.h"
@implementation ShowCollectionViewCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
self.backgroundColor = [UIColor whiteColor];
CGRect rect = self.bounds;
rect.origin.x += 3;
rect.origin.y += 3;
rect.size.height -= 6;
rect.size.width -= 6;
_showImageView = [[UIImageView alloc] initWithFrame:rect];
[self addSubview:_showImageView];
}
return self;
}
@end
RootViewController.m
#import "RootViewController.h"
#import "ShowCollectionViewCell.h"
#import "LargeUICollectionViewFlowLayout.h"
#import "YXGCD.h"
#import "SDWebImage.h"
// 重用标示
static NSString *identify = @"ItemIdentifier";
// 数据源
#define SOURCE_DATA @"http://www.duitang.com/album/1733789/masn/p/0/100/"
@interface RootViewController ()<UICollectionViewDelegate, UICollectionViewDataSource>
@property (nonatomic, strong) UICollectionView *collectionView;
@property (nonatomic, strong) NSMutableArray *dataArray; // 数据源
@end
@implementation RootViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 初始化数据源
_dataArray = [[NSMutableArray alloc] init];
// 初始化UICollectionView并指定一个UICollectionViewFlowLayout
self.collectionView = \
[[UICollectionView alloc] initWithFrame:self.view.bounds
collectionViewLayout:[LargeUICollectionViewFlowLayout new]];
// 给UICollectionViewCell注册重用标示(collectionView会自动给我们创建重用的cell对象)
[self.collectionView registerClass:[ShowCollectionViewCell class]
forCellWithReuseIdentifier:@"ItemIdentifier"];
// 设置代理对象
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
// 将UICollectionView添加进父视图
[self.view addSubview:_collectionView];
[[GCDQueue globalQueue] execute:^{
// 获取json数据
NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:SOURCE_DATA]];
// 转换数据
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableLeaves|| NSJSONReadingMutableContainers
error:nil];
if (dataDictionary)
{
NSArray *dataArray = dataDictionary[@"data"][@"blogs"];
for (NSDictionary *dic in dataArray)
{
NSLog(@"%@", dic[@"isrc"]);
// 存储数据
[_dataArray addObject:dic[@"isrc"]];
}
}
// 主线程更新
[[GCDQueue mainQueue] execute:^{
[self.collectionView reloadData];
}];
}];
}
-(NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section
{
return [_dataArray count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
ShowCollectionViewCell *cell = \
[collectionView dequeueReusableCellWithReuseIdentifier:@"ItemIdentifier"
forIndexPath:indexPath];
[cell.showImageView setImageWithURL:[NSURL URLWithString:_dataArray[indexPath.row]]];
return cell;
}
@end
效果图如下:
一款显示壁纸的软件就这么搞定雏形了......
我们来尝试一下实时更换layout让图片自动布局,效果如下:
源码:
#import "RootViewController.h"
#import "ShowCollectionViewCell.h"
#import "LargeUICollectionViewFlowLayout.h"
#import "AnotherCollectionViewFlowLayout.h"
#import "YXGCD.h"
#import "SDWebImage.h"
// 重用标示
static NSString *identify = @"ItemIdentifier";
// 数据源
#define SOURCE_DATA @"http://www.duitang.com/album/1733789/masn/p/0/100/"
@interface RootViewController ()<UICollectionViewDelegate, UICollectionViewDataSource>
@property (nonatomic, strong) UICollectionView *collectionView;
@property (nonatomic, strong) LargeUICollectionViewFlowLayout *largeLayout;
@property (nonatomic, strong) AnotherCollectionViewFlowLayout *anotherLayout;
@property (nonatomic, strong) NSMutableArray *dataArray; // 数据源
@end
@implementation RootViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 初始化数据源
_dataArray = [[NSMutableArray alloc] init];
// 初始化两种布局
_largeLayout = [LargeUICollectionViewFlowLayout new];
_anotherLayout = [AnotherCollectionViewFlowLayout new];
// 初始化UICollectionView并指定一个UICollectionViewFlowLayout
self.collectionView = \
[[UICollectionView alloc] initWithFrame:self.view.bounds
collectionViewLayout:_largeLayout];
// 给UICollectionViewCell注册重用标示(collectionView会自动给我们创建重用的cell对象)
[self.collectionView registerClass:[ShowCollectionViewCell class]
forCellWithReuseIdentifier:@"ItemIdentifier"];
// 设置代理对象
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
// 将UICollectionView添加进父视图
[self.view addSubview:_collectionView];
[[GCDQueue globalQueue] execute:^{
// 获取json数据
NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:SOURCE_DATA]];
// 转换数据
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableLeaves|| NSJSONReadingMutableContainers
error:nil];
if (dataDictionary)
{
NSArray *dataArray = dataDictionary[@"data"][@"blogs"];
for (NSDictionary *dic in dataArray)
{
NSLog(@"%@", dic[@"isrc"]);
// 存储数据
[_dataArray addObject:dic[@"isrc"]];
}
}
// 主线程更新
[[GCDQueue mainQueue] execute:^{
[self.collectionView reloadData];
// 3s后切换布局动画
[[GCDQueue mainQueue] execute:^{
[_largeLayout invalidateLayout];
[_collectionView setCollectionViewLayout:_anotherLayout
animated:YES];
} afterDelay:NSEC_PER_SEC * 3];
}];
}];
}
-(NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section
{
return [_dataArray count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
ShowCollectionViewCell *cell = \
[collectionView dequeueReusableCellWithReuseIdentifier:@"ItemIdentifier"
forIndexPath:indexPath];
[cell.showImageView setImageWithURL:[NSURL URLWithString:_dataArray[indexPath.row]]];
return cell;
}
@end
RootViewController.m
AnotherCollectionViewFlowLayout.h + AnotherCollectionViewFlowLayout.m
#import <UIKit/UIKit.h>
@interface AnotherCollectionViewFlowLayout : UICollectionViewFlowLayout
@end
#import "AnotherCollectionViewFlowLayout.h"
@implementation AnotherCollectionViewFlowLayout
- (instancetype)init
{
self = [super init];
if (self)
{
self.itemSize = CGSizeMake(150, 200); // 单元格尺寸
self.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0); // 单元格边缘
self.minimumInteritemSpacing = 10.0f; // 横排单元格最小间隔
self.minimumLineSpacing = 20.0f; // 单元格最小行间距
}
return self;
}
@end
几个核心的地方:(布局变化时自动匹配对于UICollectionView很重要哦)
so easy :)