瀑布流
1.RootViewController.h
#import <UIKit/UIKit.h>
#import "UICollectionViewWaterfallLayout.h"
@interface RootViewController : UIViewController<UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateWaterfallLayout>
@property (strong, nonatomic) UICollectionView *collectionView;
#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;}
#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; // 每个item的attributes
@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;}
@interface UICollectionViewWaterfallLayout()
@property (nonatomic, assign) NSInteger itemCount; //item的个数
@property (nonatomic, assign) CGFloat interitemSpacing; //每行每列的间隔
@property (nonatomic, strong) NSMutableArray *columnHeights; // 每一列的总高度
@property (nonatomic, strong) NSMutableArray *itemAttributes; // 每个item的attributes
@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;
#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);
}
@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