汽车公司可能用到的知识点需要马上研究的iOS接下来要研究的知识点

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

2016-12-30  本文已影响0人  来自南方的熊

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

![Simulator Screen Shot 2016年11月23日 下午6.08.56.png](https://img.haomeiwen.com/i3026808/7ddd94148013a68f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

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

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

上一篇下一篇

猜你喜欢

热点阅读