CollectionView瀑布流添加头视图,自定义Cell计算高度

来源:互联网 发布:程序员必读书籍 活着 编辑:程序博客网 时间:2024/04/30 05:42

在开发时,看到CollectionView制作的瀑布流图册很好看,于是就做了一个,效果确实可以。刚好在开发时有这种布局需求,于是把之前做的瀑布流拿来改进,还是遇到了许多问题。

先看一下效果,




首先是,需求加了个头视图在顶部,在collectionView中的头视图跟TableView的不一样,TableView只要设置

tableview.tableHeaderView就可以了,而collectionView需要在代理中设置头,尾视图。


- (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;

}


但是你会发现,使用瀑布流的时候,UICollectionViewFlowLayout是自定义的布局,collectionView的代理不会走,在网上搜了很多也没有什么解决方法,都是一个版本的复制粘贴使用这种代理方法来设置的,因为他们没用使用自定义的瀑布流布局,Cell都是相同大小的布局,所以,这里就比较坑了。

最后在CocoChina的一个论坛搜到一个说加HeaderView的,看了一下,就是在自定义的Layout中添加加一个 Header类型的 UICollectionViewLayoutAttributes就可以。然后我把瀑布流的Cell的起始位置从headerView的最大Y开始布局。这样设置之后,controllerView中的代理方法才会走,要记得注册头视图哦,不然会崩。

然后还有一个问题就是,瀑布流自定义布局,这个网上很多,不懂的自己搜,我也是照网上的做,一开始内容都是图片,只要在自定义的Layout中根据当前cell的图片设置该cell的布局大小就行。方法也是先走的layout中的设置方法,再走CollectionView的代理方法,所以这里就比较坑了,要先把每个cell的大小根据内容计算出来给layout布局设置,再去代理方法中设置自定义的Cell的内容。一开始内容是一张图片还好,只要每次取出来计算image.size就可以了,而需求是自定义的cell中有图片,文字的一些内容,所以只能专门写一个计算cell宽高的类。网上有人写了个缓存这个宽高值的类,我就没有去做了。我贴一下关键的代码吧。

自定义的瀑布流布局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)];

    }

    //计算所有cell的布局属性

    [self.attributeArrayremoveAllObjects];

    

    //头部视图

    UICollectionViewLayoutAttributes * layoutHeader = [UICollectionViewLayoutAttributeslayoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeaderwithIndexPath:[NSIndexPathindexPathWithIndex:0]];

    layoutHeader.frame =CGRectMake(0,0, screenW, self.sectionEdge.top);

    [self.attributeArrayaddObject:layoutHeader];

    

    //item内容视图

    NSInteger count = [self.collectionViewnumberOfItemsInSection:0];

    for (int i =0; i < count; i ++) {

        UICollectionViewLayoutAttributes * attribute = [selflayoutAttributesForItemAtIndexPath:[NSIndexPathindexPathForRow:iinSection:0]];

        [self.attributeArrayaddObject:attribute];

    }

    

}


controllerView中要注册Cell和头,这里的cell和头都是自定义的,

[_communityCollectionViewregisterClass:[CommunityCollectionViewCellclass]forCellWithReuseIdentifier:@"CollectionCell"];

    [_communityCollectionViewregisterClass:[CommunityHeaderViewclass]forSupplementaryViewOfKind:UICollectionElementKindSectionHeaderwithReuseIdentifier:@"HeaderView"];



在拿到请求数据的地方调用该方法为自定义的瀑布流Layout设置高度回调,里面的方法是根据数据内容来计算布局高度的,这个根据自己的内容来计算。

#pragma mark - 计算Item高度回调

- (void)counterItemHightByCommunityDataArray:(NSArray *)dataArray

{

    _communityLayout.itemHightBlock = ^CGFloat (NSIndexPath * index,CGFloat width){

        

        CGFloat itemH = [cellHCountercountCellHightByCommunityData:communityDataArray[index.item]];


        return itemH;

    };

}


然后collectionView的Heard头视图设置代理就可以走了,设置一下自定义的头视图,

- (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;

}


好了,关键的代码就这些了。



0 1
原创粉丝点击