UICollectionView 瀑布流 添加表头视图的坑框架
首先是,需求加了个头视图在顶部,在collectionView中的头视图跟TableView的不同,TableView的表头只要设置tableview.tableHeaderView就能够了. collectionView 怎么添加这样的效果的呢布局
有两种思路atom
第一种:在collectionView的段头代理中设置 (只在第一段中设置)spa
第二种:改变 collectionView 的内延距离, 而后添加在内延空白的位置.代理
第一种code
// 返回头视图 - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { UICollectionReusableView *reusableView =nil; //返回段头段尾视图 if ([kind isEqualToString:UICollectionElementKindSectionHeader]) { HMCollectionReusableView *header=[collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:headerViewIdentifier forIndexPath:indexPath]; //添加头视图的内容 header.backgroundColor = [UIColor redColor]; reusableView = header; return reusableView; } //若是底部视图 if (kind ==UICollectionElementKindSectionFooter) { UICollectionReusableView *footerview = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"FooterView"forIndexPath:indexPath]; footerview.backgroundColor = [UIColor purpleColor]; reusableView = footerview; } return reusableView; }
可是你会发现,使用瀑布流的时候,,Cell都是不一样大小的布局,UICollectionViewFlowLayout是自定义的布局,collectionView的代理不会走,因此,这里就比较坑了。orm
怎么解决呢 就是在自定义的Layout中添加加一个 Header类型的 UICollectionViewLayoutAttributes就能够。而后我把瀑布流的Cell的起始位置从headerView的最大Y开始布局。这样设置以后,controllerView中的代理方法才会走,要记得注册头视图哦,否则会崩。blog
注册段头rem
//注册段头部视图 [collectionView registerClass:[HMCollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerViewIdentifier];
//xibstring
[collectionView registerNib:[UINib nibWithNibName:@"HMCollectionReusableView" bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerViewIdentifier];
自定义的布局 HMWaterflowLayout : UICollectionViewLayout
.h
@interface HMWaterflowLayout : UICollectionViewLayout @property (nonatomic, assign) UIEdgeInsets sectionInset; /** 段头的size */ @property (nonatomic, assign) CGSize headerReferenceSize; /** 每一列之间的间距 */ @property (nonatomic, assign) CGFloat columnMargin; /** 每一行之间的间距 */ @property (nonatomic, assign) CGFloat rowMargin; /** 显示多少列 */ @property (nonatomic, assign) int columnsCount; @property (nonatomic, weak) id<HMWaterflowLayoutDelegate> delegate; @end
.m
#import <UIKit/UIKit.h> @class HMWaterflowLayout; @protocol HMWaterflowLayoutDelegate <NSObject> - (CGFloat)waterflowLayout:(HMWaterflowLayout *)waterflowLayout heightForWidth:(CGFloat)width atIndexPath:(NSIndexPath *)indexPath; @end#import "HMWaterflowLayout.h" @interface HMWaterflowLayout(); /** 这个字典用来存储每一列最大的Y值(每一列的高度) */ @property (nonatomic, strong) NSMutableDictionary *maxYDict; /** 存放全部的布局属性 */ @property (nonatomic, strong) NSMutableArray *attrsArray; @end @implementation HMWaterflowLayout - (NSMutableDictionary *)maxYDict { if (!_maxYDict) { self.maxYDict = [[NSMutableDictionary alloc] init]; } return _maxYDict; } - (NSMutableArray *)attrsArray { if (!_attrsArray) { self.attrsArray = [[NSMutableArray alloc] init]; } return _attrsArray; } - (instancetype)init { if (self = [super init]) { self.columnMargin = 10; self.rowMargin = 10; self.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10); self.columnsCount = 3; //若是段头的高度不一致 能够仿照UICollectionViewFlowLayout的代理 本身写一个代理方法返回 CGSize self.headerReferenceSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 140); } return self; } - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { return YES; } /** * 每次布局以前的准备 */ - (void)prepareLayout { [super prepareLayout]; // 1.清空最大的Y值 [self.maxYDict removeAllObjects]; for (int i = 0; i<self.columnsCount; i++) { NSString *column = [NSString stringWithFormat:@"%d", i]; self.maxYDict[column] = @(self.sectionInset.top); } // 2.计算全部cell的属性 [self.attrsArray removeAllObjects]; //头部视图 UICollectionViewLayoutAttributes * layoutHeader = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader withIndexPath:[NSIndexPath indexPathWithIndex:0]]; layoutHeader.frame =CGRectMake(0,0, self.headerReferenceSize.width, self.headerReferenceSize.height); [self.attrsArray addObject:layoutHeader]; //item内容视图 NSInteger count = [self.collectionView numberOfItemsInSection:0]; for (int i = 0; i<count; i++) { UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]]; [self.attrsArray addObject:attrs]; } } /** * 返回全部的尺寸 */ - (CGSize)collectionViewContentSize { __block NSString *maxColumn = @"0"; [self.maxYDict enumerateKeysAndObjectsUsingBlock:^(NSString *column, NSNumber *maxY, BOOL *stop) { if ([maxY floatValue] > [self.maxYDict[maxColumn] floatValue]) { maxColumn = column; } }]; //包括段头headerView的高度 return CGSizeMake(0, [self.maxYDict[maxColumn] floatValue] + self.sectionInset.bottom + self.headerReferenceSize.height ); } /** * 返回indexPath这个位置Item的布局属性 */ - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { // 假设最短的那一列的第0列 __block NSString *minColumn = @"0"; // 找出最短的那一列 [self.maxYDict enumerateKeysAndObjectsUsingBlock:^(NSString *column, NSNumber *maxY, BOOL *stop) { if ([maxY floatValue] < [self.maxYDict[minColumn] floatValue]) { minColumn = column; } }]; // 计算尺寸 CGFloat width = (self.collectionView.frame.size.width - self.sectionInset.left - self.sectionInset.right - (self.columnsCount - 1) * self.columnMargin)/self.columnsCount; CGFloat height = [self.delegate waterflowLayout:self heightForWidth:width atIndexPath:indexPath]; // 计算位置 CGFloat x = self.sectionInset.left + (width + self.columnMargin) * [minColumn intValue]; CGFloat y = [self.maxYDict[minColumn] floatValue] + self.rowMargin; // 更新这一列的最大Y值 self.maxYDict[minColumn] = @(y + height); // 建立属性 UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; //把瀑布流的Cell的起始位置从headerView的最大Y开始布局 attrs.frame = CGRectMake(x, self.headerReferenceSize.height + y, width, height ); return attrs; } /** * 返回rect范围内的布局属性 */ - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { return self.attrsArray; } @end
第二种
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, 320, self.view.frame.size.height) collectionViewLayout:flowlayout]; self.collectionView.contentInset = UIEdgeInsetsMake(50, 0, 0, 0); UIImageView *imagev = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"015.png"]]; imagev.frame = CGRectMake(0, -50, 320, 50); [self.collectionView addSubview: imagev]; [self.view addSubview: _collectionView];
提示: UICollectionReusableView 段头是能够自定义的 第一种比较好
注意:UITableView 有两个样式布局 1.Group 2.Plain (段头能够停留) 而UICollectionView 须要本身写布局 要想实现Plain (段头能够停留)的效果能够找一些网上的第三方的框架参考一下