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 (段頭能夠停留)的效果能夠找一些網上的第三方的框架參考一下