UICollectionView是一种类似于UITableView但又比UITableView功能更强大、更灵活的视图,这是源于它将UICollectionView对cell的布局交给了UICollectionViewLayout,而且允许用户自定义layout来进行布局。
UICollectionView中cell 的自动布局是从左到右一个挨着一个依次布局,当放不下时自动换行,这些是由UICollectionViewLayout决定的,UICollectionViewLayout中有一些方法和属性由系统提供可以控制UICollectionView布局。如:UICollectionViewScrollDirection 控制滑动方向;
UICollectionView需要遵守的协议也和UITableView类似,UICollectionViewDataSource,UICollectionViewDelegate;,,,,,,(UICollectionViewDelegateFlowLayout 是 UICollectionViewDelegate 的子协议;
UICollectionViewCell 需要注册 方法为
[self.collection registerClass:[CCCollectionCell class] forCellWithReuseIdentifier:@"cellID"];
self.collectionregisterNib:[UINibnibWithNibName:@"CCCollectionCell"bundle:nil]forCellWithReuseIdentifier:@"cellID"]
}
需要实现的协议方法也与UITableView的类似,此为必须实现协议方法
设置组数和item
代码中注视item 也就是文章中的cell;
UICollectionView的组header 和 footer 需要创建或者自定义UICollectionReusableView;
同样需要先注册,方法:
[self.collection registerClass:[CCCollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"footer"]; [self.collection registerNib:[UINib nibWithNibName:@"CCCollectionReusableView" bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"footer"];
方法参数kind 为两个常量字符串为UICollectionElementKindSectionFooter UICollectionElementKindSectionHeader
分别标记Resuableview 为头还是尾 参数identifier:标记,与cell的identifier作用相同。ollectionEUICollectionElementKindSectionHeader
需要实现两个方法
1.
2.
只有1方法实现了才会执行2方法。
自定义 UICollectionViewLayout
1.实现的方法
//- (void)prepareLayout
/**
* 决定了collectionView的contentSize
- (CGSize)collectionViewContentSize
*/
/**
* 说明所有元素(比如cell、补充控件、装饰控件)的布局属性
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
*/
/**
* 说明cell的布局属性
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:
通过这些方法完成布局,代码如下
//#import "CCWaterFlowLayout.h"
//
//#define CCCollectionW self.collectionView.frame.size.width
//
///** 每一行之间的间距 */
//static const CGFloat CCDefaultRowMargin = 10;
///** 每一列之间的间距 */
//static const CGFloat CCDefaultColumnMargin = 10;
///** 每一列之间的间距 top, left, bottom, right */
//static const UIEdgeInsets CCDefaultInsets = {10, 10, 10, 10};
///** 默认的列数 */
//static const int CCDefaultColumsCount = 3;
//
//@interface CCWaterFlowLayout()
//
///** 每一列的最大Y值 */
//@property (nonatomic, strong) NSMutableArray *columnMaxYs;
///** 存放所有cell的布局属性 */
//@property (nonatomic, strong) NSMutableArray *attrsArray;
//
//@end
//
//@implementation CCWaterFlowLayout
//
//#pragma mark - 懒加载
//- (NSMutableArray *)columnMaxYs
//{
// if (!_columnMaxYs) {
// _columnMaxYs = [[NSMutableArray alloc] init];
// }
// return _columnMaxYs;
//}
//
//- (NSMutableArray *)attrsArray
//{
// if (!_attrsArray) {
// _attrsArray = [[NSMutableArray alloc] init];
// }
// return _attrsArray;
//}
//
//#pragma mark - 实现内部的方法
///**
// * 决定了collectionView的contentSize
// - (CGSize)collectionViewContentSize
// */
//- (CGSize)collectionViewContentSize
//{
// // 找出最长那一列的最大Y值
// CGFloat destMaxY = [self.columnMaxYs[0] doubleValue];
// for (NSUInteger i = 1; i<self.columnMaxYs.count; i++) {
// // 取出第i列的最大Y值
// CGFloat columnMaxY = [self.columnMaxYs[i] doubleValue];
//
// // 找出数组中的最大值
// if (destMaxY < columnMaxY) {
// destMaxY = columnMaxY;
// }
// }
// return CGSizeMake(0, destMaxY + CCDefaultInsets.bottom);
//}
- (void)prepareLayout
//- (void)prepareLayout
//{
// [super prepareLayout];
//
// // 重置每一列的最大Y值
// [self.columnMaxYs removeAllObjects];
// for (NSUInteger i = 0; i<CCDefaultColumsCount; i++) {
// [self.columnMaxYs addObject:@(CCDefaultInsets.top)];
// NSLog(@"maxY=%@",self.columnMaxYs);
//
// }
//
// // 计算所有cell的布局属性
// [self.attrsArray removeAllObjects];
// NSUInteger count = [self.collectionView numberOfItemsInSection:0];
// for (NSUInteger i = 0; i < count; ++i) {
// NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
// UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath];
// [self.attrsArray addObject:attrs];
// NSLog(@"attrs=%@",self.attrsArray);
//
// }
//
// NSLog(@"maxY=%@---attrs=%@",self.columnMaxYs,self.attrsArray);
//}
//
///**
// * 说明所有元素(比如cell、补充控件、装饰控件)的布局属性
// - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
// */
//- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
//{
// return self.attrsArray;
//}
//
///**
// * 说明cell的布局属性
// - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
// */
//- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
//{
// UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
//
// /** 计算indexPath位置cell的布局属性 */
//
// // 水平方向上的总间距
// CGFloat xMargin = CCDefaultInsets.left + CCDefaultInsets.right + (CCDefaultColumsCount - 1) * CCDefaultColumnMargin;
// // cell的宽度
// CGFloat w = (CCCollectionW - xMargin) / CCDefaultColumsCount;
// // cell的高度,测试数据,随机数
// CGFloat h = 50 + arc4random_uniform(150);
//
// // 找出最短那一列的列号 和最大Y值
// CGFloat destMaxY = [self.columnMaxYs[0] doubleValue];
// NSUInteger destColumn = 0;
// for (NSUInteger i = 1; i<self.columnMaxYs.count; i++) {
// // 取出第i列的最大Y值
// CGFloat columnMaxY = [self.columnMaxYs[i] doubleValue];
//
// // 找出数组中的最小值
// if (destMaxY > columnMaxY) {
// destMaxY = columnMaxY;
// destColumn = i;
// }
// }
//
// // cell的x值
// CGFloat x = CCDefaultInsets.left + destColumn * (w + CCDefaultColumnMargin);
// // cell的y值
// CGFloat y = destMaxY + CCDefaultRowMargin;
// // cell的frame
// attrs.frame = CGRectMake(x, y, w, h);
//
// // 更新数组中的最大Y值
// self.columnMaxYs[destColumn] = @(CGRectGetMaxY(attrs.frame));
//
// return attrs;
//}
//
//@end
执行效果: