第一弹
萌猫导航
首页 » 技术 » iOS

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

作者: 怪哈哈小编 来源: 怪哈哈网 日期: 2017-08-25 16:57:29 人气: -

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

先看一下效果,

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



首先是,需求加了个头视图在顶部,在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;

}


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


转载请注明文章来源(欢迎分享): http://www.guaihaha.com/ios/17177.html

怪哈哈动漫图库
关于怪哈哈
怪哈哈是一个集搞笑,美女,动漫,游戏,技术等为核心的综合性网站!
联系我们
商务洽谈、广告合作、友情链接、侵权举报,这些都可以联系我们哦!
关于我们 - 联系我们 - 广告服务 - 免责申明   
本站文字和图片均为严格审查筛选收藏,均收集整理于互联网,其著作权归原作者所有,如果有侵犯您权利的照片,请来信告知,我们将及时撤销相应文字和图片.
Copyright @2014-2020 怪哈哈网 All Rights Reserved.
【谢谢大家一直支持贵站】