本实例主要涉及UICollectionView和UICollectionViewFlowLayout

源码:https://github.com/ianzhengnan/WaterFall

极客学院视频地址:http://www.jikexueyuan.com/course/492.html

效果图:



开发小技巧:

对于比较长的方法名,只需记住返回值的类型,输入返回值类型和view名就可以通过xcode的提示得出想要的方法。


实现步骤如下:

1. 在ViewController.h中加入UICollectionView

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UICollectionViewDelegateFlowLayout, UICollectionViewDataSource>

@property (nonatomic, strong) UICollectionView *collectionView;



@end

2. 在ViewController.m中懒加载读取图片

//lazy load
- (NSArray *)imgArr{
    if(!_imgArr){
    
        NSMutableArray *muArr = [NSMutableArray array];
        for (int i = 0; i < kImgCount; i++) {
            UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"huoying%d",i + 1]];
            [muArr addObject:image];
        }
        _imgArr = muArr;
    }
    return _imgArr;
}

3. 在View did load方法中创建CollectionView. 注册Cell.并把它们加入到主View中。

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    //create collection view layout first
    WaterFallFlowLayout *flowLayout = [[WaterFallFlowLayout alloc] init];
    self.collectionView = [[UICollectionView alloc] initWithFrame:[UIScreen mainScreen].bounds
                                             collectionViewLayout:flowLayout];
    self.collectionView.backgroundColor = [UIColor yellowColor];
    self.collectionView.delegate = self;
    self.collectionView.dataSource = self;
    //register cell
    [self.collectionView registerClass:[WaterFallCollectionViewCell class] forCellWithReuseIdentifier:identifier];
   
    [self.view addSubview:self.collectionView];
}

4. 设置numberOfItemsInSection

5. 创建Cell

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    
    WaterFallCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
    
    if (!cell) {
        cell = [[WaterFallCollectionViewCell alloc] init];
    }
    cell.image = self.imgArr[indexPath.item];
    return cell;
}

6. 设置图片的新尺寸,获取edge值

// set the new size of images
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
    
    UIImage *image = self.imgArr[indexPath.item];
    float height = [self imgHeight:image.size.height width:image.size.width];
    return CGSizeMake(100, height);
}
//set the margin
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{

    UIEdgeInsets edgeInsets = {5,5,5,5};
    return edgeInsets;
    
}

7. 创建新类继承自UICollectionViewFlowLayout 在此类中设置CollectionView 的layout

//
//  WaterFallFlowLayout.m
//  WaterFall
//
//  Created by zhengna on 15/6/29.
//  Copyright (c) 2015年 zhengna. All rights reserved.
//

#import "WaterFallFlowLayout.h"

CGFloat const colCount = 3;

@implementation WaterFallFlowLayout

//set the layout of cell
//prepare for the setting of layout
- (void)prepareLayout{
    
    [super prepareLayout];
    _colArr = [NSMutableArray array];
    _attributeDict = [NSMutableDictionary dictionary];
    self.delegate = (id<UICollectionViewDelegateFlowLayout>)self.collectionView.delegate;
    _cellCount = [self.collectionView numberOfItemsInSection:0];
    
    if(_cellCount == 0){
        return;
    }
    float top = 0;
    for (int i = 0; i < colCount; i++) {
        [_colArr addObject:[NSNumber numberWithFloat:top]];
    }
    for (int i = 0; i < _cellCount; i++) {
        [self layoutItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
    }
}

//set layout for cells
- (void)layoutItemAtIndexPath:(NSIndexPath *)indexPath{
    //get the padding of cells through invoking delegate methods
    UIEdgeInsets edgeInsets = [self.delegate collectionView:self.collectionView layout:self
                                     insetForSectionAtIndex:indexPath.row];
    
    //get the size of every items
    CGSize itemSize = [self.delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath];
    
    //find the minimun height
    float col = 0;
    float shortHeight = [[_colArr objectAtIndex:col] floatValue];
    for (int i = 0; i < _colArr.count; i++) {
        float height = [[_colArr objectAtIndex:i] floatValue];
        if(height < shortHeight){
            shortHeight = height;
            col = i;
        }
    }
    float top = [[_colArr objectAtIndex:col] floatValue];
    //set the frame value of cell
    CGRect frame = CGRectMake(edgeInsets.left + col * (edgeInsets.left + itemSize.width), top + edgeInsets.top, itemSize.width, itemSize.height);
    //update the height of column
    [_colArr replaceObjectAtIndex:col withObject:[NSNumber numberWithFloat:top + edgeInsets.top + itemSize.height]];
    
    //save the indexPath of cell to dictronary
    [_attributeDict setObject:indexPath forKey:NSStringFromCGRect(frame)];
}

- (NSArray *)indexPathsOfItem:(CGRect)rect{

    NSMutableArray *array = [NSMutableArray array];
    for (NSString *rectStr in _attributeDict) {
        CGRect cellRect = CGRectFromString(rectStr);
        //
        if (CGRectIntersectsRect(cellRect, rect)) {
            NSIndexPath *indexPath = _attributeDict[rectStr];
            [array addObject:indexPath];
        }
    }
    return array;
}
//get the layout info
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{

    NSMutableArray * muArr = [NSMutableArray array];
    //according the param of frame to calcute the which cell should be appear
    NSArray *indexPaths = [self indexPathsOfItem:rect];
    for (NSIndexPath *indexPath in indexPaths) {
        UICollectionViewLayoutAttributes *attribute = [self layoutAttributesForItemAtIndexPath:indexPath];
        [muArr addObject:attribute];
    }
    return muArr;
}

//calcute the size of collection view's content
- (CGSize)collectionViewContentSize{
    //get the heightest height
    CGSize size = self.collectionView.frame.size;
    float maxHeight = [[_colArr objectAtIndex:0] floatValue];
    for (int i = 0; i < _colArr.count; i++) {
        float colHeight = [[_colArr objectAtIndex:i] floatValue];
        if (colHeight > maxHeight) {
            maxHeight = colHeight;
        }
    }
    size.height = maxHeight;
    return size;
}

@end





Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐