有时候想给不同的section设置不同的列,用这个就可以了
#import <UIKit/UIKit.h>
@protocol CCCollectionViewLayoutDelegate;
NS_ASSUME_NONNULL_BEGIN
@interface CCCollectionViewLayout : UICollectionViewLayout
@property (nonatomic, assign) CGFloat minimumLineSpacing;
@property (nonatomic, assign) CGFloat minimumInteritemSpacing;
@property (nonatomic, weak) id<CCCollectionViewLayoutDelegate> delegate;
@end
@protocol CCCollectionViewLayoutDelegate <NSObject>
@required
-(NSInteger)ccCollectionView:(UICollectionView *)collectionView layout:(CCCollectionViewLayout *)layout numberOfColumnInSection:(NSInteger)section;
-(NSInteger)ccCollectionView:(UICollectionView *)collectionView layout:(CCCollectionViewLayout *)layout width:(CGFloat)width heightForItemAtIndexPath:(NSIndexPath *)indexPath;
@optional
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(CCCollectionViewLayout *)layout minimumLineSpacingForSectionAtIndex:(NSInteger)section;
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(CCCollectionViewLayout *)layout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(CCCollectionViewLayout *)layout insetForSectionAtIndex:(NSInteger)section;
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(CCCollectionViewLayout *)layout referenceHeightForHeaderInSection:(NSInteger)section;
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(CCCollectionViewLayout *)layout referenceHeightForFooterInSection:(NSInteger)section;
@end
NS_ASSUME_NONNULL_END
m文件
#import "CCCollectionViewLayout.h"
@interface CCCollectionViewLayout ()
@property (nonatomic, strong) NSMutableArray<NSMutableArray<UICollectionViewLayoutAttributes *> *> *itemLayoutAttributes;
@property (nonatomic, assign) CGFloat contentHeight;
@end
@implementation CCCollectionViewLayout
-(void)prepareLayout{
[super prepareLayout];
if (self.collectionView.isDecelerating || self.collectionView.isDragging) {
return;
}
_contentHeight=0.0;
self.itemLayoutAttributes=[NSMutableArray new];
UICollectionView *collectionView = self.collectionView;
NSInteger const numberOfSections = collectionView.numberOfSections;
UIEdgeInsets const contentInset = collectionView.contentInset;
CGFloat const contentWidth = collectionView.bounds.size.width - contentInset.left - contentInset.right;
for (NSInteger section=0; section<numberOfSections; section++) {
NSInteger const columnOfSection = [self.delegate ccCollectionView:collectionView layout:self numberOfColumnInSection:section];
UIEdgeInsets const contentInsetOfSection = [self contentInsetForSection:section];
CGFloat const minimumLineSpacing = [self minimumLineSpacingForSection:section];
CGFloat const minimumInteritemSpacing = [self minimumInteritemSpacingForSection:section];
CGFloat const contentWidthOfSection = contentWidth - contentInsetOfSection.left - contentInsetOfSection.right;
CGFloat const itemWidth = (contentWidthOfSection-(columnOfSection-1)*minimumInteritemSpacing) / columnOfSection;
NSInteger const numberOfItems = [collectionView numberOfItemsInSection:section];
// The current section's offset for per column.
CGFloat headerHeight = 0.0;
CGFloat offsetOfColumns[columnOfSection];
for (NSInteger i=0; i<columnOfSection; i++) {
offsetOfColumns[i] = headerHeight + contentInsetOfSection.top;
}
NSMutableArray *layoutAttributeOfSection = [NSMutableArray arrayWithCapacity:numberOfItems];
for (NSInteger item=0; item<numberOfItems; item++) {
// Find minimum offset and fill to it.
NSInteger currentColumn = 0;
for (NSInteger i=1; i<columnOfSection; i++) {
if (offsetOfColumns[currentColumn] > offsetOfColumns[i]) {
currentColumn = i;
}
}
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:item inSection:section];
CGFloat itemHeight=[self.delegate ccCollectionView:collectionView layout:self width:itemWidth heightForItemAtIndexPath:indexPath];
CGFloat x = contentInsetOfSection.left + itemWidth*currentColumn + minimumInteritemSpacing*currentColumn;
CGFloat y = offsetOfColumns[currentColumn] + (item>=columnOfSection ? minimumLineSpacing : 0.0);
UICollectionViewLayoutAttributes *layoutAttbiture = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
layoutAttbiture.frame = CGRectMake(x, y+self.contentHeight, itemWidth, itemHeight);
[layoutAttributeOfSection addObject:layoutAttbiture];
// Update y offset in current column
offsetOfColumns[currentColumn] = (y + itemHeight);
}
[self.itemLayoutAttributes addObject:layoutAttributeOfSection];
// Get current section height from offset record.
CGFloat maxOffsetValue = offsetOfColumns[0];
for (int i=1; i<columnOfSection; i++) {
if (offsetOfColumns[i] > maxOffsetValue) {
maxOffsetValue = offsetOfColumns[i];
}
}
maxOffsetValue += contentInsetOfSection.bottom;
// [self.heightOfSections addObject:@(maxOffsetValue)];
self.contentHeight += maxOffsetValue;
}
}
- (CGSize)collectionViewContentSize {
UIEdgeInsets contentInset = self.collectionView.contentInset;
CGFloat width = CGRectGetWidth(self.collectionView.bounds) - contentInset.left - contentInset.right;
CGFloat height = MAX(CGRectGetHeight(self.collectionView.bounds), _contentHeight);
return CGSizeMake(width, height);
}
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
NSMutableArray<UICollectionViewLayoutAttributes *> *result = [NSMutableArray array];
[self.itemLayoutAttributes enumerateObjectsUsingBlock:^(NSMutableArray<UICollectionViewLayoutAttributes *> *layoutAttributeOfSection, NSUInteger idx, BOOL *stop) {
[layoutAttributeOfSection enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes *attribute, NSUInteger idx, BOOL *stop) {
if (CGRectIntersectsRect(rect, attribute.frame)) {
[result addObject:attribute];
}
}];
}];
return result;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
return self.itemLayoutAttributes[indexPath.section][indexPath.item];
}
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
return YES;
}
#pragma mark Private
- (UIEdgeInsets)contentInsetForSection:(NSInteger)section {
UIEdgeInsets edgeInsets = UIEdgeInsetsZero;
if ([self.delegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)]) {
edgeInsets = [self.delegate collectionView:self.collectionView layout:self insetForSectionAtIndex:section];
}
return edgeInsets;
}
- (CGFloat)minimumLineSpacingForSection:(NSInteger)section {
CGFloat minimumLineSpacing = self.minimumLineSpacing;
if ([self.delegate respondsToSelector:@selector(collectionView:layout:minimumLineSpacingForSectionAtIndex:)]) {
minimumLineSpacing = [self.delegate collectionView:self.collectionView layout:self minimumLineSpacingForSectionAtIndex:section];
}
return minimumLineSpacing;
}
- (CGFloat)minimumInteritemSpacingForSection:(NSInteger)section {
CGFloat minimumInteritemSpacing = self.minimumInteritemSpacing;
if ([self.delegate respondsToSelector:@selector(collectionView:layout:minimumInteritemSpacingForSectionAtIndex:)]) {
minimumInteritemSpacing = [self.delegate collectionView:self.collectionView layout:self minimumInteritemSpacingForSectionAtIndex:section];
}
return minimumInteritemSpacing;
}
@end