在開(kāi)發(fā)時(shí),看到CollectionView制作的瀑布流圖冊(cè)很好看,于是就做了一個(gè),效果確實(shí)可以。剛好在開(kāi)發(fā)時(shí)有這種布局需求,于是把之前做的瀑布流拿來(lái)改進(jìn),還是遇到了許多問(wèn)題。
先看一下效果,

首先是,需求加了個(gè)頭視圖在頂部,在collectionView中的頭視圖跟TableView的不一樣,TableView只要設(shè)置
tableview.tableHeaderView就可以了,而collectionView需要在代理中設(shè)置頭,尾視圖。
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionReusableView *reusableView =nil;
if (kind ==UICollectionElementKindSectionHeader) {
UICollectionReusableView *header = [collectionViewdequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeaderwithReuseIdentifier:@"HeaderView"forIndexPath:indexPath];
reusableView = header;
}
reusableView.backgroundColor = [UIColorgreenColor];
if (kind ==UICollectionElementKindSectionFooter)
{
UICollectionReusableView *footerview = [collectionViewdequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooterwithReuseIdentifier:@"FooterView"forIndexPath:indexPath];
footerview.backgroundColor = [UIColorpurpleColor];
reusableView = footerview;
}
return reusableView;
}
但是你會(huì)發(fā)現(xiàn),使用瀑布流的時(shí)候,UICollectionViewFlowLayout是自定義的布局,collectionView的代理不會(huì)走,在網(wǎng)上搜了很多也沒(méi)有什么解決方法,都是一個(gè)版本的復(fù)制粘貼使用這種代理方法來(lái)設(shè)置的,因?yàn)樗麄儧](méi)用使用自定義的瀑布流布局,Cell都是相同大小的布局,所以,這里就比較坑了。
最后在CocoChina的一個(gè)論壇搜到一個(gè)說(shuō)加HeaderView的,看了一下,就是在自定義的Layout中添加加一個(gè) Header類型的 UICollectionViewLayoutAttributes就可以。然后我把瀑布流的Cell的起始位置從headerView的最大Y開(kāi)始布局。這樣設(shè)置之后,controllerView中的代理方法才會(huì)走,要記得注冊(cè)頭視圖哦,不然會(huì)崩。
然后還有一個(gè)問(wèn)題就是,瀑布流自定義布局,這個(gè)網(wǎng)上很多,不懂的自己搜,我也是照網(wǎng)上的做,一開(kāi)始內(nèi)容都是圖片,只要在自定義的Layout中根據(jù)當(dāng)前cell的圖片設(shè)置該cell的布局大小就行。方法也是先走的layout中的設(shè)置方法,再走CollectionView的代理方法,所以這里就比較坑了,要先把每個(gè)cell的大小根據(jù)內(nèi)容計(jì)算出來(lái)給layout布局設(shè)置,再去代理方法中設(shè)置自定義的Cell的內(nèi)容。一開(kāi)始內(nèi)容是一張圖片還好,只要每次取出來(lái)計(jì)算image.size就可以了,而需求是自定義的cell中有圖片,文字的一些內(nèi)容,所以只能專門寫一個(gè)計(jì)算cell寬高的類。網(wǎng)上有人寫了個(gè)緩存這個(gè)寬高值的類,我就沒(méi)有去做了。我貼一下關(guān)鍵的代碼吧。
自定義的瀑布流布局Layout中,添加頭和cell的Attribute,
- (void)prepareLayout
{
[superprepareLayout];
CGFloat screenW =CGRectGetWidth([UIScreenmainScreen].bounds);
// 重置每一列的最大Y值
[self.columnMaxYArrayremoveAllObjects];
for (int i =0; i < self.columnCount; i ++) {
[self.columnMaxYArrayaddObject:@(self.sectionEdge.top)];
}
//計(jì)算所有cell的布局屬性
[self.attributeArrayremoveAllObjects];
//頭部視圖
UICollectionViewLayoutAttributes * layoutHeader = [UICollectionViewLayoutAttributeslayoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeaderwithIndexPath:[NSIndexPathindexPathWithIndex:0]];
layoutHeader.frame =CGRectMake(0,0, screenW, self.sectionEdge.top);
[self.attributeArrayaddObject:layoutHeader];
//item內(nèi)容視圖
NSInteger count = [self.collectionViewnumberOfItemsInSection:0];
for (int i =0; i < count; i ++) {
UICollectionViewLayoutAttributes * attribute = [selflayoutAttributesForItemAtIndexPath:[NSIndexPathindexPathForRow:i inSection:0]];
[self.attributeArrayaddObject:attribute];
}
}
controllerView中要注冊(cè)Cell和頭,這里的cell和頭都是自定義的,
[_communityCollectionViewregisterClass:[CommunityCollectionViewCellclass]forCellWithReuseIdentifier:@"CollectionCell"];
[_communityCollectionViewregisterClass:[CommunityHeaderViewclass] forSupplementaryViewOfKind:UICollectionElementKindSectionHeaderwithReuseIdentifier:@"HeaderView"];
在拿到請(qǐng)求數(shù)據(jù)的地方調(diào)用該方法為自定義的瀑布流Layout設(shè)置高度回調(diào),里面的方法是根據(jù)數(shù)據(jù)內(nèi)容來(lái)計(jì)算布局高度的,這個(gè)根據(jù)自己的內(nèi)容來(lái)計(jì)算。
#pragma mark - 計(jì)算Item高度回調(diào)
- (void)counterItemHightByCommunityDataArray:(NSArray *)dataArray
{
_communityLayout.itemHightBlock = ^CGFloat (NSIndexPath * index,CGFloat width){
CGFloat itemH = [cellHCountercountCellHightByCommunityData:communityDataArray[index.item]];
return itemH;
};
}
然后collectionView的Heard頭視圖設(shè)置代理就可以走了,設(shè)置一下自定義的頭視圖,
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionReusableView * reusableview =nil;
if (kind ==UICollectionElementKindSectionHeader){
_heardView = [collectionViewdequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeaderwithReuseIdentifier:@"HeaderView"forIndexPath:indexPath];
reusableview = _heardView;
}
return reusableview;
}
好了,關(guān)鍵的代碼就這些了。