當(dāng)系統(tǒng)給出的布局屬性UIcollectionViewFlowLayout不能滿(mǎn)足我們的需求的時(shí)候,我們就需要自己來(lái)定義一個(gè)我們需要的布局屬性,來(lái)完成我們的需求,那么該怎么做呢?下面我將給出一個(gè)詳細(xì)的demo給大家用參考,代碼中均有詳細(xì)的注釋解釋,希望對(duì)大家能有幫助.
// XY_WaterFlowLayout.h
// UI15_CustomCollectionViewLayout
//
// Created by 歲變 on 16/8/3.
// Copyright ? 2016年 歲變. All rights reserved.
//
#import <UIKit/UIKit.h>
@protocol XY_WaterFlowLayoutDelegate <NSObject>
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
width:(CGFloat)width
heightForItemAtIndexPath:(NSIndexPath *)indexPath;
@end
//自定義布局繼承于 UICollectionViewLayout
@interface XY_WaterFlowLayout : UICollectionViewLayout
@property (nonatomic, weak) id <XY_WaterFlowLayoutDelegate> 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; //列數(shù)
@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; //保存布局屬性的數(shù)組
@property (nonatomic, strong) NSMutableArray *arrHeightForColumns;//保存每列的高度
@property (nonatomic, assign) NSInteger shortestColumnsIndex; //最短列坐標(biāo)
@property (nonatomic, assign) NSInteger longestColumnsIndex; //最長(zhǎng)列坐標(biāo)
@end
@implementation XY_WaterFlowLayout
- (instancetype)init {
self = [super init];
if (self) {
//默認(rèn)值 :列數(shù)2
// :橫向間距10
// :縱向間距10
// :據(jù)四周邊距 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 必須重寫(xiě)三個(gè)方法
- (void)prepareLayout {
[super prepareLayout];
self.attributesArrary = [NSMutableArray array];
self.arrHeightForColumns = [NSMutableArray array];
//給每一列添加上邊距的距離
[self addTopSectionInsetsForColums];
//獲取item 的個(gè)數(shù) [self.collectionView numberOfItemsInSection:0]
for (int i = 0; i < [self.collectionView numberOfItemsInSection:0]; i++) {
//為每個(gè)item創(chuàng)建布局屬性 并添加到數(shù)組中
UICollectionViewLayoutAttributes *layoutAttributes = [self setLayoutAttributesForItems:[NSIndexPath indexPathForItem:i inSection:0]];
[_attributesArrary addObject:layoutAttributes];
}
}
//返回每個(gè)item的布局屬性
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
return _attributesArrary;
}
//負(fù)責(zé)滾動(dòng)范圍
- (CGSize)collectionViewContentSize {
//獲取最長(zhǎng)列坐標(biāo)
NSInteger longextIndex = [self getLongestColumnsIndex];
//獲取最長(zhǎng)列的長(zhǎng)度
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)];
}
}
//生成每個(gè)item的不屬性 主要是fram屬性
- (UICollectionViewLayoutAttributes *)setLayoutAttributesForItems:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
//item的原點(diǎn)坐標(biāo)
CGPoint origin = [self originForItem];
//通過(guò)代理獲取寬和高
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);
//更新數(shù)組里的列高度
_arrHeightForColumns[_shortestColumnsIndex] = @(origin.y + height);
return layoutAttributes;
}
//計(jì)算原點(diǎn)坐標(biāo)
- (CGPoint)originForItem {
//最短列
_shortestColumnsIndex = [self getShortestColumnsIndex];
//計(jì)算原點(diǎn)坐標(biāo).x 左邊距 + (item寬度 + item橫向間距) * shorestColumnsIndex
CGFloat x = _sectionInsets.left + (self.itemWidth + self.horizontalSpace) * _shortestColumnsIndex;
//計(jì)算原點(diǎn)坐標(biāo).y
CGFloat y = [_arrHeightForColumns[_shortestColumnsIndex] floatValue] + _verticalSpace;
CGPoint origin = CGPointMake(x, y);
return origin;
}
//記錄最短列的坐標(biāo)
- (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;
}
//記錄最長(zhǎng)列的坐標(biāo)
- (NSInteger)getLongestColumnsIndex {
//記錄最長(zhǎng)列
NSInteger longestIndex = 0;
//最長(zhǎng)列高度
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