//
// JKMasonryLayout.h
// CollectionViewCustomerLayout
//
// Created by Jack on 2017/7/3.
// Copyright © 2017年 buakaw.lee.com.www. All rights reserved.
//
#import <UIKit/UIKit.h>
@class JKMasonryLayout;
@protocol JKMasonryLayoutDelegate <NSObject>
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(JKMasonryLayout *)layout heightForItemAtIndexPath:(NSIndexPath *)indexPath;
@end
@interface JKMasonryLayout : UICollectionViewLayout
@property (nonatomic,assign) NSUInteger numberOfColumns;
@property (nonatomic,assign) CGFloat interItemSpacing;
@property (nonatomic,weak) id<JKMasonryLayoutDelegate> delegate;
@end
//
// JKMasonryLayout.m
// CollectionViewCustomerLayout
//
// Created by Jack on 2017/7/3.
// Copyright © 2017年 buakaw.lee.com.www. All rights reserved.
//
#import "JKMasonryLayout.h"
@implementation JKMasonryLayout {
CGFloat maxY;
NSArray *attrs;
}
- (void)prepareLayout {
/**
* 布局过程之前被调用
* 在此方法中计算边框,numberOfColumns 和 interItemSpacing 决定宽度,高度由代理决定
*
*/
maxY = 0;
NSUInteger numberOfItem = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:0];
NSMutableArray *attrsArr = [NSMutableArray arrayWithCapacity:numberOfItem];
CGFloat colY[self.numberOfColumns];
for (int i = 0; i < self.numberOfColumns; i++) {
colY[i] = 0;
}
for (int i = 0; i < numberOfItem; i++) {
// int row = i / self.numberOfColumns;
int col = i % self.numberOfColumns;
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
CGFloat fullWidth = self.collectionView.bounds.size.width;
CGFloat availableSpaceExcludingPadding = fullWidth - self.interItemSpacing * (self.numberOfColumns + 1);
CGFloat itemWidth = availableSpaceExcludingPadding / self.numberOfColumns;
CGFloat itemHeight = [self.delegate collectionView:self.collectionView layout:self heightForItemAtIndexPath:indexPath];
CGFloat x = self.interItemSpacing + (itemWidth + self.interItemSpacing) * col;
CGFloat y = self.interItemSpacing + colY[col];
CGRect frame = CGRectMake(x, y, itemWidth, itemHeight);
maxY = CGRectGetMaxY(frame) > maxY ? CGRectGetMaxY(frame) : maxY;
colY[col] = CGRectGetMaxY(frame);
UICollectionViewLayoutAttributes *itemAttrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
itemAttrs.frame = frame;
[attrsArr addObject:itemAttrs];
}
attrs = attrsArr;
maxY += self.interItemSpacing;
}
- (CGSize)collectionViewContentSize {
return CGSizeMake(self.collectionView.frame.size.width, maxY);
}
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
__block NSMutableArray *attrsArr = [NSMutableArray array];
[attrs enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (CGRectIntersectsRect(rect, obj.frame)) {
[attrsArr addObject:obj];
}
}];
return attrsArr;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath {
return nil;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath {
return nil;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *itemtAttrs = [self->attrs objectAtIndex:indexPath.row];
return itemtAttrs;
}
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
CGRect oldBounds = self.collectionView.bounds;
if (!CGSizeEqualToSize(newBounds.size, oldBounds.size)) {
return YES;
}
return NO;
}
@end