UICollectView 瀑布流與Header的坑

1.繪製瀑布流的時候,如果沒有對Layout做特殊處理,會導致header的代理方法不執行

分析原因:重寫佈局的時候(prepareLayout此方法),只對cell佈局進行的處理,而沒有加入header的佈局屬性

解決辦法:重寫佈局的時候(prepareLayout此方法)加上header的佈局

2.貼上代碼

.h文件

@interface ZTYWaterflowLayout : UICollectionViewFlowLayout

- (instancetype)initRowMargin:(CGFloat)rowMargin SectionMargin:(CGFloat)sectionMargin rowCount:(NSInteger)rowCount colInsets:(UIEdgeInsets)colInsets fixCellH:(NSInteger)cellHeight;

@end

 

.m文件

 

/** 默認的列數 */

static const NSInteger CXDDefaultColumnCount = 2;

/** 每一列之間的間距 */

static const CGFloat CXDDefaultColumnMargin = 7;

/** 每一行之間的間距 */

static const CGFloat CXDDefaultRowMargin = 7;

/** 邊緣間距 */

static const UIEdgeInsets CXDDefaultEdgeInsets = {0, 12, 0, 12};

 

 

@interface ZTYWaterflowLayout ()

/** 存放所有cell的佈局屬性 */

@property (nonatomic, strong) NSMutableArray *attrsArray;

/** 存放所有列的當前高度 */

@property (nonatomic, strong) NSMutableArray *columnHeights;

 

@property (assign,nonatomic) CGFloat rowMargin;

@property (assign,nonatomic) CGFloat sectionMargin;

@property (assign,nonatomic) NSInteger rowCount;

@property (assign,nonatomic) UIEdgeInsets colInsets;

@property (assign,nonatomic) CGFloat cellHeight;

 

@end

 

@implementation ZTYWaterflowLayout

 

- (NSMutableArray *)columnHeights

{

    if (!_columnHeights) {

        _columnHeights = [NSMutableArray array];

    }

    return _columnHeights;

}

 

- (NSMutableArray *)attrsArray

{

    if (!_attrsArray) {

        _attrsArray = [NSMutableArray array];

    }

    return _attrsArray;

}

- (instancetype)initRowMargin:(CGFloat)rowMargin SectionMargin:(CGFloat)sectionMargin rowCount:(NSInteger)rowCount colInsets:(UIEdgeInsets)colInsets fixCellH:(NSInteger)cellHeight

{

    self = [super init];

    if (self) {

        _rowMargin = rowMargin;

        _sectionMargin = sectionMargin;

        _rowCount = rowCount;

        _colInsets = colInsets;

        _cellHeight = cellHeight;

    }

    return self;

}

 

- (instancetype)init

{

    self = [super init];

    if (self) {

        _rowMargin = CXDDefaultRowMargin;

        _sectionMargin = CXDDefaultColumnMargin;

        _rowCount = CXDDefaultColumnCount;

        _colInsets = CXDDefaultEdgeInsets;

 

  

    }

    return self;

}

 

/**

* 初始化

*/

- (void)prepareLayout

{

    [super prepareLayout];

    

    // 清除以前計算的所有高度

    [self.columnHeights removeAllObjects];

    for (NSInteger i = 0; i < _rowCount; i++) {

        [self.columnHeights addObject:@(_colInsets.top+self.headerReferenceSize.height)];  // 注意別忘了把header的高度也加上

    }

    

    // 清除之前所有的佈局屬性

    [self.attrsArray removeAllObjects];

    

    

    //頭部視圖 加入header佈局屬性

    UICollectionViewLayoutAttributes * layoutHeader = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader withIndexPath:[NSIndexPath indexPathWithIndex:0]];

    layoutHeader.frame =CGRectMake(0,0, self.headerReferenceSize.width, self.headerReferenceSize.height);

    [self.attrsArray addObject:layoutHeader];

    

    // 開始創建每一個cell對應的佈局屬性

    NSInteger count = [self.collectionView numberOfItemsInSection:0];

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

        // 創建位置

        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];

        // 獲取indexPath位置cell對應的佈局屬性

        UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath];

        [self.attrsArray addObject:attrs];

    }

}

 

/**

* 決定cell的排布

*/

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect

{

    return self.attrsArray;

}

 

/**

* 返回indexPath位置cell對應的佈局屬性

*/

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath

{

    // 創建佈局屬性

    UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

    

    // collectionView的寬度

    CGFloat collectionViewW = self.collectionView.frame.size.width;

    

    // 設置佈局屬性的frame

    CGFloat w = (collectionViewW - _colInsets.left - _colInsets.right - (_rowCount - 1) * _sectionMargin) / _rowCount;

    CGFloat h = 50 + arc4random_uniform(100);

    if (indexPath.row % 2 == 1) {

        h = 285;

    }else{

        h = 307;

    }

    

    if (_cellHeight > 0) {

        h = _cellHeight;

    }

    

    // 找出高度最短的那一列

    NSInteger destColumn = 0;

    CGFloat minColumnHeight = [self.columnHeights[0] doubleValue];

    for (NSInteger i = 1; i < _rowCount; i++) {

        // 取得第i列的高度

        CGFloat columnHeight = [self.columnHeights[i] doubleValue];

        

        if (minColumnHeight > columnHeight) {

            minColumnHeight = columnHeight;

            destColumn = i;

        }

    }

    

    CGFloat x = _colInsets.left + destColumn * (w + _sectionMargin);

    CGFloat y = minColumnHeight ;

 

    if (y != _colInsets.top) {

        y += _rowMargin;

    }

    attrs.frame = CGRectMake(x, y , w, h);

    

    // 更新最短那列的高度

    self.columnHeights[destColumn] = @(CGRectGetMaxY(attrs.frame));

    

    return attrs;

}

 

- (CGSize)collectionViewContentSize

{

    CGFloat maxColumnHeight = [self.columnHeights[0] doubleValue];

    for (NSInteger i = 1; i < _rowCount; i++) {

        // 取得第i列的高度

        CGFloat columnHeight = [self.columnHeights[i] doubleValue];

        

        if (maxColumnHeight < columnHeight) {

            maxColumnHeight = columnHeight;

        }

    }

    return CGSizeMake(0, maxColumnHeight + _colInsets.bottom);

}

@end

 

 

3.使用

    ZTYWaterflowLayout * layout = [[ZTYWaterflowLayout alloc] init];

    layout.headerReferenceSize = CGSizeMake(kSCREEN_WIDTH, 200); // 設置header的尺寸

    

    ZTYCollectionView * collview = [[ZTYCollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];

    collview.delegate = self;

    collview.dataSource = self;

    [self.view addSubview:collview];

 

    [collview registerClass:[GoodsCollectionCell class] forCellWithReuseIdentifier:@"goodscell"];

    [collview registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"];

// 代理方法

-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{

    UICollectionReusableView * reusaview = nil;

    

    if (kind == UICollectionElementKindSectionHeader) {

        reusaview = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"pageHead" forIndexPath:indexPath];

        UIView * headview = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)];

        [reusaview addSubview:headview];

    }    

    return reusaview;

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章