瀑布流

1.RootViewController.h
#import <UIKit/UIKit.h>
#import "UICollectionViewWaterfallLayout.h"
@interface RootViewController : UIViewController<UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateWaterfallLayout>
@property (strong, nonatomic) UICollectionView *collectionView;

@end
 
2.RootViewController.m
#import "RootViewController.h"
#import "UICollectionViewWaterfallCell.h"
#import "DetailViewController.h"

#define CELL_WIDTH 145
#define CELL_IDENTIFIER @"WaterfallCell"

@interface RootViewController ()
@property (nonatomic, strong) NSMutableArray *cellHeights;
@property (nonatomic, strong) NSMutableArray *images;
@end

@implementation RootViewController

#pragma mark - Accessors
- (UICollectionView *)collectionView
{
    if (!_collectionView) {
        UICollectionViewWaterfallLayout *layout = [[UICollectionViewWaterfallLayout alloc] init];
       
        layout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
        layout.delegate = self;
       
       
        _collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
        _collectionView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
        _collectionView.dataSource = self;
        _collectionView.delegate = self;
        _collectionView.backgroundColor = [UIColor blackColor];
        [_collectionView registerClass:[UICollectionViewWaterfallCell class]
            forCellWithReuseIdentifier:CELL_IDENTIFIER];
    }
    return _collectionView;
}

//- (NSMutableArray *)cellHeights
//{
//    if (!_cellHeights) {
//        _cellHeights = [NSMutableArray arrayWithCapacity:_images.count];
//        for (NSInteger i = 0; i < _images.count; i++) {
//            _cellHeights[i] = @(arc4random()%100*2+100);
//        }
//    }
//    return _cellHeights;
//}

#pragma mark - Life Cycle

- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
    [self.view addSubview:self.collectionView];
    self.title = @"WaterFallFlow";
   
    _images = [[NSMutableArray alloc]initWithObjects:
               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",
               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpgg",
               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",
               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",
               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",
               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",
               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",
               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",
               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",
               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",
               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",
               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",
               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",               @"http://img.alicdn.com/tfscom///img.alicdn.com/tfscom/TB1S.zkIpXXXXbwXpXXXXXXXXXX_290x10000.jpg",nil];}- (void)viewDidAppear:(BOOL)animated{    [super viewDidAppear:animated];    [self updateLayout];}- (void)didReceiveMemoryWarning{    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation                                         duration:(NSTimeInterval)duration{    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation                                            duration:duration];    [self updateLayout];}- (void)updateLayout{    UICollectionViewWaterfallLayout *layout =    (UICollectionViewWaterfallLayout *)self.collectionView.collectionViewLayout;    layout.columnCount = (self.collectionView.bounds.size.width-layout.sectionInset.left-layout.sectionInset.right) / CELL_WIDTH;    layout.itemWidth = CELL_WIDTH;}#pragma mark - UICollectionViewDataSource- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{    return _images.count;}- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{    return 1;}- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView                  cellForItemAtIndexPath:(NSIndexPath *)indexPath{    UICollectionViewWaterfallCell *cell =    (UICollectionViewWaterfallCell *)[collectionView dequeueReusableCellWithReuseIdentifier:CELL_IDENTIFIER forIndexPath:indexPath];    cell.imageView.imageURL = [NSURL URLWithString:[_images objectAtIndex:indexPath.row]];    return cell;}- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{    NSLog(@"-------------%ld",indexPath.item);    DetailViewController *detailVC = [[DetailViewController alloc]init];    [self.navigationController pushViewController:detailVC animated:YES];    detailVC.imageStr = (self.images)[indexPath.item];}#pragma mark - UICollectionViewWaterfallLayoutDelegate- (CGFloat)collectionView:(UICollectionView *)collectionView                   layout:(UICollectionViewWaterfallLayout *)collectionViewLayout heightForItemAtIndexPath:(NSIndexPath *)indexPath{    return arc4random()%200+100;}
@end
 
 
3.UICollectionViewWaterfallLayout.h
 

#import <UIKit/UIKit.h>

@class UICollectionViewWaterfallLayout;
@protocol UICollectionViewDelegateWaterfallLayout <UICollectionViewDelegate>
- (CGFloat)collectionView:(UICollectionView *)collectionView
                   layout:(UICollectionViewWaterfallLayout *)collectionViewLayout
 heightForItemAtIndexPath:(NSIndexPath *)indexPath;
@end

@interface UICollectionViewWaterfallLayout : UICollectionViewLayout
@property (nonatomic, weak) id<UICollectionViewDelegateWaterfallLayout> delegate;
@property (nonatomic, assign) NSUInteger columnCount; // 列数
@property (nonatomic, assign) CGFloat itemWidth; // item的宽度
@property (nonatomic, assign) UIEdgeInsets sectionInset; // 每个section的边框间距
@end
 
4.UICollectionViewWaterfallLayout.m
#import "UICollectionViewWaterfallLayout.h"

@interface UICollectionViewWaterfallLayout()
@property (nonatomic, assign) NSInteger itemCount; //item的个数
@property (nonatomic, assign) CGFloat interitemSpacing;  //每行每列的间隔
@property (nonatomic, strong) NSMutableArray *columnHeights;  // 每一列的总高度
@property (nonatomic, strong) NSMutableArray *itemAttributes;  // 每个itemattributes
@end

@implementation UICollectionViewWaterfallLayout

#pragma mark - Accessors
- (void)setColumnCount:(NSUInteger)columnCount
{
    if (_columnCount != columnCount) {
        _columnCount = columnCount;
        [self invalidateLayout];
    }
}

- (void)setItemWidth:(CGFloat)itemWidth
{
    if (_itemWidth != itemWidth) {
        _itemWidth = itemWidth;
        [self invalidateLayout];
    }
}

- (void)setSectionInset:(UIEdgeInsets)sectionInset
{
    if (!UIEdgeInsetsEqualToEdgeInsets(_sectionInset, sectionInset)) {
        _sectionInset = sectionInset;
        [self invalidateLayout];
    }
}

#pragma mark - Init
- (void)commonInit
{
    _columnCount = 2;
    _itemWidth = 150.0f;
    _sectionInset = UIEdgeInsetsZero;
}

- (id)init
{
    self = [super init];
    if (self) {
        [self commonInit];
    }
    return self;
}

#pragma mark - Life cycle
- (void)dealloc
{
    [_columnHeights removeAllObjects];
    _columnHeights = nil;

    [_itemAttributes removeAllObjects];
    _itemAttributes = nil;
}

#pragma mark - Methods to Override
- (void)prepareLayout
{
    [super prepareLayout];

    _itemCount = [[self collectionView] numberOfItemsInSection:0];

    NSAssert(_columnCount > 1, @"columnCount for UICollectionViewWaterfallLayout should be greater than 1.");
    CGFloat width = self.collectionView.frame.size.width - _sectionInset.left - _sectionInset.right;
    _interitemSpacing = floorf((width - _columnCount * _itemWidth) / (_columnCount - 1));    _itemAttributes = [NSMutableArray arrayWithCapacity:_itemCount];    _columnHeights = [NSMutableArray arrayWithCapacity:_columnCount];       for (NSInteger idx = 0; idx < _columnCount; idx++) {        [_columnHeights addObject:@(_sectionInset.top)];    }    // Item will be put into shortest column.    for (NSInteger idx = 0; idx < _itemCount; idx++) {        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:idx inSection:0];        CGFloat itemHeight = [self.delegate collectionView:self.collectionView                                                    layout:self                                  heightForItemAtIndexPath:indexPath];        NSUInteger columnIndex = [self shortestColumnIndex];        CGFloat xOffset = _sectionInset.left + (_itemWidth + _interitemSpacing) * columnIndex;        CGFloat yOffset = [(_columnHeights[columnIndex]) floatValue];        UICollectionViewLayoutAttributes *attributes =        [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];        attributes.frame = CGRectMake(xOffset, yOffset, self.itemWidth, itemHeight);        [_itemAttributes addObject:attributes];        _columnHeights[columnIndex] = @(yOffset + itemHeight + _interitemSpacing);    }}- (CGSize)collectionViewContentSize{    if (self.itemCount == 0) {        return CGSizeZero;    }    CGSize contentSize = self.collectionView.frame.size;    NSUInteger columnIndex = [self longestColumnIndex];    CGFloat height = [self.columnHeights[columnIndex] floatValue];    contentSize.height = height - self.interitemSpacing + self.sectionInset.bottom;    return contentSize;}- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)path{    return (self.itemAttributes)[path.item];}- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{    return [self.itemAttributes filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(UICollectionViewLayoutAttributes *evaluatedObject, NSDictionary *bindings) {        return CGRectIntersectsRect(rect, [evaluatedObject frame]);    }]];}- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{    return NO;}#pragma mark - Private Methods// Find out shortest column.- (NSUInteger)shortestColumnIndex{    __block NSUInteger index = 0;    __block CGFloat shortestHeight = MAXFLOAT;    [self.columnHeights enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {        CGFloat height = [obj floatValue];        if (height < shortestHeight) {            shortestHeight = height;            index = idx;        }    }];    return index;}// Find out longest column.- (NSUInteger)longestColumnIndex{    __block NSUInteger index = 0;    __block CGFloat longestHeight = 0;    [self.columnHeights enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {        CGFloat height = [obj floatValue];        if (height > longestHeight) {            longestHeight = height;            index = idx;        }    }];    return index;}
@end
 
5.UICollectionViewWaterfallCell.h
#import <UIKit/UIKit.h>
#import "EGOImageView.h"
@interface UICollectionViewWaterfallCell : UICollectionViewCell

@property (strong, nonatomic) EGOImageView *imageView;

@end
 
6.UICollectionViewWaterfallCell.m
#import "UICollectionViewWaterfallCell.h"

@implementation UICollectionViewWaterfallCell

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

- (EGOImageView *)imageView
{
    if (!_imageView) {
        _imageView = [[EGOImageView alloc]init];
        _imageView.backgroundColor = [UIColor greenColor];
        [self.contentView addSubview:_imageView];
    }
    return _imageView;
}

- (void)layoutSubviews
{
    _imageView.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
}

@end
 
7.DetailViewController.h

#import <UIKit/UIKit.h>

@interface DetailViewController : UIViewController

@property (nonatomic, strong) NSString *imageStr;

@end
 
8.DetailViewController.m

#import "DetailViewController.h"
#import "EGOImageView.h"
@interface DetailViewController ()

@end

@implementation DetailViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor blackColor];
   
    EGOImageView *imageView = [[EGOImageView alloc]initWithFrame:self.view.bounds];
    imageView.imageURL = [NSURL URLWithString:self.imageStr];
    imageView.contentMode = UIViewContentModeScaleAspectFit;
    [self.view addSubview:imageView];
// Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
posted @ 2016-03-10 08:59  莫念莫忘  阅读(86)  评论(0编辑  收藏  举报