OC-建立瀑布流

 

1. 建立「WYWaterflowLayout」繼承製  「UICollectionViewLayout」。數組

2. 在「ViewController」 中導入「WYWaterflowLayout」類。並建立,建立的代碼以下dom

@property (nonatomic,weak) UICollectionView *collectionView;佈局

- (void)CircleLayout
{
    WYWaterflowLayout *layout = [[WYWaterflowLayout alloc] init];
      
    // 建立CollectionView
    UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
    collectionView.dataSource = self;
    collectionView.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:collectionView];
    
    self.collectionView = collectionView;
    
    // 使用系統自帶的類註冊
   // [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:WYShopID];
    
    // 使用自定義類註冊
    [collectionView registerNib:[UINib nibWithNibName:NSStringFromClass([XMGShopCell class]) bundle:nil] forCellWithReuseIdentifier:WYShopID];
}

 

3. 數據源<UICollectionViewDataSource>atom

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    self.collectionView.footer.hidden = self.shops.count == 0;
    return self.shops.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{

    XMGShopCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:WYShopID forIndexPath:indexPath];
    XMGShop *shopses = self.shops[indexPath.item];
    cell.shop = shopses;
    
    return cell;
}

4. 寫 「WYWaterflowLayout」的方法,這四個類是必需要寫的。spa

// 初始化

- (void)prepareLayout;

// 決定cell的排布

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;

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

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

- (CGSize)collectionViewContentSize

 總體代碼以下:code

//
//  WYWaterflowLayout.m
//  瀑布流
//
//  Created by baojia on 16/8/26.
//  Copyright © 2016年 OS. All rights reserved.
//

#import "WYWaterflowLayout.h"

/** 默認的列數 */
static const NSInteger WYColumnCount = 3 ;
/** 每列之間的間距 */
static const CGFloat   WYColumnMargin = 10 ;
/** 每行之間的間距 */
static const CGFloat   WYRowMarage   = 20;
/** 邊緣距離 */
static const UIEdgeInsets WYEdgeInsets = {10,10,10,10};


@interface WYWaterflowLayout ()
@property (nonatomic,strong) NSMutableArray   *attrsArray;
/** 存放全部列的當前高度 */
@property (nonatomic,strong) NSMutableArray   *columnHeights;

@end

@implementation WYWaterflowLayout
- (NSMutableArray *)columnHeights
{
    if (_columnHeights == nil)
    {
        _columnHeights = [NSMutableArray array];
    }
    return _columnHeights ;
}

- (NSMutableArray *)attrsArray
{
    if (_attrsArray == nil)
    {
        _attrsArray = [NSMutableArray array];
    }
    return _attrsArray ;
}

// 初始化
- (void)prepareLayout
{
    [super prepareLayout];
    
    // 清楚之前計算的全部高度
    [self.columnHeights removeAllObjects];
    
    for (NSInteger i = 0; i < WYColumnCount; i++) {
        [self.columnHeights addObject:@(WYEdgeInsets.top)];
    }

    // 清空以前全部的佈局屬性
    [self.attrsArray removeAllObjects];
    
    // 添加布局屬性
    [self arrayPrepareLayout];

}

// 決定cell的排布
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
    // 這個方法會頻繁的調用,每次這個界面進行滾動的時候都會調用這個方法,當這個類繼承製「UICollectionViewLayout」的時候。
    // 瀑布流算好一遍就能夠了,因此能夠放在初始化中弄。
    
    return self.attrsArray;
}

// 返回indexPath位置cell對應的佈局屬性
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    // 2. 建立佈局屬性
    UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    
    // collectionView的寬度
    CGFloat collectionView_W = self.collectionView.frame.size.width;
    
    // 3. 設置佈局屬性的frame
    CGFloat attrs_W = (collectionView_W - WYEdgeInsets.left - WYEdgeInsets.right - (WYColumnCount - 1) * WYColumnMargin) / WYColumnCount;
    CGFloat attrs_H = 50 + arc4random_uniform(100);
    
    /* 第一種方法
    // 3.1 找出高度最短的那一列
    __block NSInteger destColumn = 0 ;
    __block CGFloat minColumnHeight = MAXFLOAT;
    
    [self.columnHeights enumerateObjectsUsingBlock:^(NSNumber *columnHeightNumber, NSUInteger idx, BOOL * _Nonnull stop) {
        
        CGFloat columnHeight = columnHeightNumber.doubleValue;
        
        if (minColumnHeight > columnHeight) {
            minColumnHeight = columnHeight;
            destColumn = idx;
        }
    }];
     */
    
    // 第二種寫法
    NSInteger destColumn = 0;
    CGFloat mincolumnHeight = [self.columnHeights[0] doubleValue];
    for (NSInteger i = 1; i < WYColumnCount; i++) {
        // 取得第一列的高度
        CGFloat columnHeight = [self.columnHeights[i] doubleValue];
        
        if (mincolumnHeight > columnHeight) {
            mincolumnHeight = columnHeight;
            destColumn = i;
        }
    }
    
 
    CGFloat attrs_X = WYEdgeInsets.left + destColumn * (attrs_W + WYColumnMargin);
    
    CGFloat attrs_Y = mincolumnHeight;
    if (attrs_Y != WYEdgeInsets.top) {
        attrs_Y += WYRowMarage;
    }
    
    attrs.frame = CGRectMake(attrs_X, attrs_Y, attrs_W, attrs_H);
    
    // 4. 更新最短那列的高度
    self.columnHeights[destColumn] = @(CGRectGetMaxY(attrs.frame));

    return attrs;
}

- (CGSize)collectionViewContentSize
{
    CGFloat maxColumnHeight = [self.columnHeights[0] doubleValue];
    for (NSInteger i = 1; i < WYColumnCount ; i++) {
        // 取得第i列額高度
        CGFloat columnHeight = [self.columnHeights[i] doubleValue];
        
        if (maxColumnHeight < columnHeight) {
            maxColumnHeight = columnHeight;
        }
    }
    return CGSizeMake(0, maxColumnHeight + WYEdgeInsets.bottom);
}

#pragma mark - cell的排布
- (NSMutableArray *)arrayPrepareLayout
{
    // 1. 建立一個數組(存放全部cell的佈局屬性)
//    NSMutableArray *arrayM = [NSMutableArray array];
    
    // 2. 開始建立每個cell對應的佈局屬性
    NSInteger count = [self.collectionView numberOfItemsInSection:0];
    
    for (NSInteger i = 0 ; i < count;  i++) {
        // 1. 建立位置
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
        
        // 2. 獲取indexPath位置cell對應的佈局
        UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath];
        [self.attrsArray addObject:attrs];
    }
    return self.attrsArray;
}
@end
相關文章
相關標籤/搜索