前言
UICollectionView 和 UICollectionViewController 类是iOS6 新引进的API,用于展示集合视图,布局更加灵活,可实现多列布局,用法类似于UITableView 和 UITableViewController 类。- 使用
UICollectionView 必须实现UICollectionViewDataSource ,UICollectionViewDelegate ,UICollectionViewDelegateFlowLayout 这三个协议。
UICollectionView 是比UITableView 更加强大的一个UI控件,有如下几个方面:
- 支持水平和垂直两种方向的布局
- 通过
layout 配置方式进行布局 - 类似于
TableView 中的cell 特性外,CollectionView 中的item 大小和位置可以自由定义 - 通过
layout 布局回调的代理方法,可以动态的定制每个item 的大小和collection 的大体布局属性 - 更加强大一点,完全自定义一套
layout 布局方案,可以实现意想不到的效果
九宫格类布局
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UICollectionViewFlowLayout * layout = [[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
layout.itemSize = CGSizeMake(100, 100);
UICollectionView * collect = [[UICollectionView alloc]initWithFrame:self.view.frame collectionViewLayout:layout];
collect.delegate = self;
collect.dataSource = self;
[collect registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellid"];
[self.view addSubview:collect];
}
这里有一点需要注意,collectionView 在完成代理回调前,必须注册一个cell ,类似如下:
[collect registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellid"];
这和tableView 有些类似,又有些不同,因为tableView 除了注册cell 的方法外,还可以通过临时创建来做:
- (nullable __kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier;
- (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);
- 然后再把协议函数补充完整,也类似于
UITableView ,分区个数、每个分区的item 个数、返回每个item
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 10;
}
- (UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellid" forIndexPath:indexPath];
cell.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1];
return cell;
}
效果如下:
- 同样,如果内容的大小超出一屏,和
tableView 类似是可以进行视图滑动的。
使用FlowLayout实现瀑布流
- 这种布局无疑在app的应用中更加广泛,商品的展示,书架书目的展示,都会倾向于采用这样的布局方式,当然,通过自定义
FlowLayout ,我们也很容易实现。
首先,我们新建一个文件继承于UICollectionViewFlowLayout :
@interface MyLayout : UICollectionViewFlowLayout
只添加一个属性,直接让外界将item 个数传递进来,我们把重心方法重写布局的方法上:
@interface MyLayout : UICollectionViewFlowLayout
@property (nonatomic, assign) int itemCount;
@end
- 前面说过,
UICollectionViewFlowLayout 是一个专门用来管理collectionView 布局的类,因此,collectionView 在进行UI布局前,会通过这个类的对象获取相关的布局信息,FlowLayout 类将这些布局信息全部存放在了一个数组中,数组中是UICollectionViewLayoutAttributes 类,这个类是对item 布局的具体设置,以后咱们在讨论这个类。 - 总之,
FlowLayout 类将每个item 的位置等布局信息放在一个数组中,在collectionView 布局时,会调用FlowLayout 类layoutAttributesForElementsInRect :方法来获取这个布局配置数组。因此,我们需要重写这个方法,返回我们自定义的配置数组,另外,FlowLayout 类在进行布局之前,会调用prepareLayout 方法,所以我们可以重写这个方法,在里面对我们的自定义配置数据进行一些设置。
简单来说,自定义一个FlowLayout 布局类就是两个步骤:
- 设计好我们的布局配置数据
prepareLayout 方法中 - 返回我们的配置数组
layoutAttributesForElementsInRect 方法中
@implementation MyLayout {
NSMutableArray * _attributeAttay;
}
- (void)prepareLayout {
_attributeAttay = [[NSMutableArray alloc] init];
[super prepareLayout];
float WIDTH = ([UIScreen mainScreen].bounds.size.width-self.sectionInset.left-self.sectionInset.right-self.minimumInteritemSpacing)/2;
CGFloat colHight[2] = { self.sectionInset.top,self.sectionInset.bottom };
for (int i=0; i < _itemCount; i++) {
NSIndexPath *index = [NSIndexPath indexPathForItem:i inSection:0];
UICollectionViewLayoutAttributes * attris = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:index];
CGFloat hight = arc4random()%150+40;
int width = 0;
if (colHight[0] < colHight[1]) {
colHight[0] = colHight[0]+hight+self.minimumLineSpacing;
width=0;
} else {
colHight[1] = colHight[1]+hight+self.minimumLineSpacing;
width = 1;
}
attris.frame = CGRectMake(self.sectionInset.left+(self.minimumInteritemSpacing+WIDTH)*width, colHight[width]-hight-self.minimumLineSpacing, WIDTH, hight);
[_attributeAttay addObject:attris];
}
if (colHight[0] > colHight[1]) {
self.itemSize = CGSizeMake(WIDTH, (colHight[0]-self.sectionInset.top)*2/_itemCount-self.minimumLineSpacing);
} else {
self.itemSize = CGSizeMake(WIDTH, (colHight[1]-self.sectionInset.top)*2/_itemCount-self.minimumLineSpacing);
}
}
- (NSArray <UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
return _attributeAttay;
}
@end
自定义完成FlowLayout后,我们在ViewController中进行使用:
- (void)viewDidLoad {
[super viewDidLoad];
MyLayout * layout = [[MyLayout alloc]init];
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
layout.itemCount = 100;
UICollectionView * collect = [[UICollectionView alloc]initWithFrame:self.view.frame collectionViewLayout:layout];
collect.delegate = self;
collect.dataSource = self;
[collect registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellid"];
[self.view addSubview:collect];
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 100;
}
- (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellid" forIndexPath:indexPath];
cell.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1];
return cell;
}
效果如下:
|