当系统给出的布局属性UIcollectionViewFlowLayout不能满足我们的需求的时候,我们就需要自己来定义一个我们需要的布局属性,来完成我们的需求,那么该怎么做呢?下面我将给出一个详细的demo给大家用参考,代码中均有详细的注释解释,希望对大家能有帮助.
// XY_WaterFlowLayout.h
// UI15_CustomCollectionViewLayout
//
// Created by 岁变 on 16/8/3.
// Copyright © 2016年 岁变. All rights reserved.
//
#import
@protocol XY_WaterFlowLayoutDelegate
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
width:(CGFloat)width
heightForItemAtIndexPath:(NSIndexPath *)indexPath;
@end
//自定义布局继承于 UICollectionViewLayout
@interface XY_WaterFlowLayout : UICollectionViewLayout
@property (nonatomic, weak) id delegate;
@property (nonatomic, assign) CGFloat itemWidth; //item的宽度
@property (nonatomic, assign) CGFloat horizontalSpace;//行间距
@property (nonatomic, assign) CGFloat verticalSpace;//竖向间距
@property (nonatomic, assign) UIEdgeInsets sectionInsets;//边距
@property (nonatomic, assign) NSInteger numberOfColumns; //列数
@end
//
// XY_WaterFlowLayout.m
// UI15_CustomCollectionViewLayout
//
// Created by 岁变 on 16/8/3.
// Copyright © 2016年 岁变. All rights reserved.
//
#import "XY_WaterFlowLayout.h"
@interface XY_WaterFlowLayout ()
@property (nonatomic, strong) NSMutableArray< UICollectionViewLayoutAttributes *> *attributesArrary; //保存布局属性的数组
@property (nonatomic, strong) NSMutableArray *arrHeightForColumns;//保存每列的高度
@property (nonatomic, assign) NSInteger shortestColumnsIndex; //最短列坐标
@property (nonatomic, assign) NSInteger longestColumnsIndex; //最长列坐标
@end
@implementation XY_WaterFlowLayout
- (instancetype)init {
self = [super init];
if (self) {
//默认值 :列数2
// :横向间距10
// :纵向间距10
// :据四周边距 10 10 10 10
_numberOfColumns = 2;
_horizontalSpace = 10;
_verticalSpace = 10;
_sectionInsets = UIEdgeInsetsMake(10, 10, 10, 10);
}
return self;
}
- (CGFloat)itemWidth {
self.itemWidth = (self.collectionView.frame.size.width - (_numberOfColumns - 1) * _horizontalSpace - _sectionInsets.left - _sectionInsets.right) / _numberOfColumns;
return _itemWidth;
}
//自定义layout 必须重写三个方法
- (void)prepareLayout {
[super prepareLayout];
self.attributesArrary = [NSMutableArray array];
self.arrHeightForColumns = [NSMutableArray array];
//给每一列添加上边距的距离
[self addTopSectionInsetsForColums];
//获取item 的个数 [self.collectionView numberOfItemsInSection:0]
for (int i = 0; i < [self.collectionView numberOfItemsInSection:0]; i++) {
//为每个item创建布局属性 并添加到数组中
UICollectionViewLayoutAttributes *layoutAttributes = [self setLayoutAttributesForItems:[NSIndexPath indexPathForItem:i inSection:0]];
[_attributesArrary addObject:layoutAttributes];
}
}
//返回每个item的布局属性
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
return _attributesArrary;
}
//负责滚动范围
- (CGSize)collectionViewContentSize {
//获取最长列坐标
NSInteger longextIndex = [self getLongestColumnsIndex];
//获取最长列的长度
CGFloat longestHeight = [_arrHeightForColumns[longextIndex] floatValue];
//获取collectionView的size
CGSize contentSize = self.collectionView.frame.size;
contentSize.height = longestHeight + _sectionInsets.bottom;
return contentSize;
}
//给每一刻加上上边距
- (void)addTopSectionInsetsForColums {
for (int i = 0; i < _numberOfColumns; i++) {
[_arrHeightForColumns addObject:@(_sectionInsets.top)];
}
}
//生成每个item的不属性 主要是fram属性
- (UICollectionViewLayoutAttributes *)setLayoutAttributesForItems:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
//item的原点坐标
CGPoint origin = [self originForItem];
//通过代理获取宽和高
CGFloat height = 0;
if ([self.delegate respondsToSelector:@selector(collectionView:layout:width:heightForItemAtIndexPath:)]) {
height = [self.delegate collectionView:self.collectionView layout:self width:self.itemWidth heightForItemAtIndexPath:indexPath];
}
layoutAttributes.frame = CGRectMake(origin.x, origin.y, self.itemWidth, height);
//更新数组里的列高度
_arrHeightForColumns[_shortestColumnsIndex] = @(origin.y + height);
return layoutAttributes;
}
//计算原点坐标
- (CGPoint)originForItem {
//最短列
_shortestColumnsIndex = [self getShortestColumnsIndex];
//计算原点坐标.x 左边距 + (item宽度 + item横向间距) * shorestColumnsIndex
CGFloat x = _sectionInsets.left + (self.itemWidth + self.horizontalSpace) * _shortestColumnsIndex;
//计算原点坐标.y
CGFloat y = [_arrHeightForColumns[_shortestColumnsIndex] floatValue] + _verticalSpace;
CGPoint origin = CGPointMake(x, y);
return origin;
}
//记录最短列的坐标
- (NSInteger) getShortestColumnsIndex {
//记录最短列
NSInteger shortestIndex = 0;
//记录最短高度
CGFloat shortestHeight = MAXFLOAT;
for (int i = 0; i < self.arrHeightForColumns.count; i++) {
CGFloat currentHeight = [self.arrHeightForColumns[i] floatValue];
if (currentHeight < shortestHeight) {
shortestHeight = currentHeight;
shortestIndex = i;
}
}
return shortestIndex;
}
//记录最长列的坐标
- (NSInteger)getLongestColumnsIndex {
//记录最长列
NSInteger longestIndex = 0;
//最长列高度
CGFloat longestHight = 0;
for (int i = 0; i < _arrHeightForColumns.count; i++) {
CGFloat currentHeight = [self.arrHeightForColumns[i] floatValue];
if (currentHeight > longestHight) {
longestHight = currentHeight;
longestIndex = i;
}
}
return longestIndex;
}
@end