自定义UICollectionViewLayout(适用于多个section)
一、自定义layout主要方法
重写系统的- (void)prepareLayout 方法;
其实就是计算每个cell的frame和其它相关属性。
二、在网上看了好多自定义的layout 但是没有多section的,就整了这个……
全部代码:
.h文件
@class ForeverGuardFlowLayout; @protocol ForeverGuardFlowLayoutDelegate <NSObject> - (CGSize)collectionView:(UICollectionView *)collectionView layout:(ForeverGuardFlowLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath; @end @interface ForeverGuardFlowLayout : UICollectionViewFlowLayout @property(nonatomic, assign)NSUInteger numberOfColumn;//列数 @property(nonatomic, assign)id<ForeverGuardFlowLayoutDelegate>delegate; @end
1 @interface ForeverGuardFlowLayout() 2 //存放每一列的高度 3 @property (nonatomic, retain) NSMutableArray *columnHeightsArray; 4 5 //每个section的每一列的高度 6 @property (nonatomic, retain) NSMutableArray *collectionHeightsArray; 7 8 //存放每一个cell的属性 9 @property (nonatomic, retain) NSMutableArray *attributesArray; 10 11 12 @end 13 @implementation ForeverGuardFlowLayout 14 15 16 /** 17 每个区的最小高度 18 19 @param section 区索引 20 @return 高度 21 */ 22 - (CGFloat)minHeightWithSection:(NSInteger)section{ 23 CGFloat min = 1000000; 24 for (NSNumber *height in _collectionHeightsArray[section]) { 25 if (min > [height floatValue]) { 26 min = [height floatValue]; 27 } 28 } 29 return min; 30 } 31 32 33 /** 34 每个区的初始Y坐标 35 36 @param section 区索引 37 @return Y坐标 38 */ 39 - (CGFloat)maxHeightWithSection:(NSInteger)section{ 40 41 if (section>0) { 42 CGFloat max = 0; 43 for (int i=0; i<section; i++) { 44 max += [self maxHeightAboutSection:_collectionHeightsArray[i]]; 45 } 46 return max; 47 }else{ 48 return 0; 49 } 50 51 } 52 53 54 /** 55 每个区的最大高度 56 57 @param dataArr 每个区的所有列的高度 58 @return 最大高度 59 */ 60 - (CGFloat)maxHeightAboutSection:(NSMutableArray *)dataArr{ 61 CGFloat max = 0; 62 for (NSNumber *heigth in dataArr) { 63 if (max < [heigth floatValue]) { 64 max = [heigth floatValue]; 65 } 66 } 67 return max; 68 69 } 70 71 72 /** 73 collectionView的显示高度 74 */ 75 - (CGFloat)collectionHeight{ 76 CGFloat max = 0; 77 for (NSMutableArray *sectionArr in _collectionHeightsArray) { 78 max += [self maxHeightAboutSection:sectionArr]; 79 } 80 return max; 81 } 82 83 84 /** 85 当前区的最小高度的索引 86 87 @param section 当前区 88 @return 最小高度的索引 89 */ 90 - (NSUInteger)indexOfMinHeightWithSection:(NSInteger)section{ 91 NSUInteger index = 0; 92 NSMutableArray *sectionArr = _collectionHeightsArray[section]; 93 for (int i=0; i<sectionArr.count; i++) { 94 CGFloat height = [sectionArr[i] floatValue]; 95 if (height == [self minHeightWithSection:section]) { 96 index = i; 97 return index; 98 } 99 } 100 return index; 101 } 102 103 104 /** 105 重写系统prepareLayout方法 (设置item的坐标等属性) 106 */ 107 - (void)prepareLayout{ 108 [super prepareLayout]; 109 110 _attributesArray = [[NSMutableArray alloc] init]; 111 112 _columnHeightsArray = [NSMutableArray arrayWithCapacity:self.numberOfColumn]; 113 114 NSUInteger sectionCount = [self.collectionView numberOfSections]; 115 _collectionHeightsArray = [NSMutableArray arrayWithCapacity:sectionCount]; 116 117 for (int index = 0; index<sectionCount; index++) { 118 NSMutableArray *columnArr = [NSMutableArray array]; 119 for (int i=0; i<self.numberOfColumn; i++) { 120 [columnArr addObject:@0.0]; 121 } 122 [_collectionHeightsArray addObject:columnArr]; 123 } 124 125 CGFloat totalWidth = self.collectionView.frame.size.width; 126 127 CGFloat x = 0; 128 CGFloat y = 0; 129 130 for (int index= 0; index<sectionCount; index++) { 131 NSUInteger itemCount = [self.collectionView numberOfItemsInSection:index]; 132 x = 0; 133 y = [self maxHeightWithSection:index]; 134 for (int i=0; i<itemCount; i++) { 135 NSUInteger numberIfSoace = self.numberOfColumn-1; 136 CGFloat spaceWidth = 7.5;//item左右间距 137 CGFloat width = (totalWidth - spaceWidth*numberIfSoace)/self.numberOfColumn; 138 139 NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:index]; 140 141 CGSize imageSize =[self.delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath]; 142 143 CGFloat height = width * imageSize.height / imageSize.width; 144 145 UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 146 147 attributes.frame = CGRectMake(x, y, width, height); 148 [_attributesArray addObject:attributes]; 149 150 151 NSUInteger minHeightIndex = [self indexOfMinHeightWithSection:index]; 152 153 CGFloat minHeight = [_collectionHeightsArray[index][minHeightIndex] floatValue]; 154 CGFloat lineHeight = 7.5;//item上下间距 155 156 _collectionHeightsArray[index][minHeightIndex] = [NSNumber numberWithFloat:minHeight+lineHeight+height]; 157 minHeightIndex = [self indexOfMinHeightWithSection:index]; 158 159 x = (spaceWidth + width) * minHeightIndex; 160 161 y += [self minHeightWithSection:index]; 162 163 } 164 165 } 166 167 } 168 169 170 /** 171 返回collectionView的界面显示大小 172 */ 173 - (CGSize)collectionViewContentSize{ 174 return CGSizeMake(self.collectionView.frame.size.width, [self collectionHeight]); 175 } 176 177 178 /** 179 将所有的layoutAttributes重写布局 180 */ 181 - (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{ 182 return _attributesArray; 183 } 184 @end
@interface ForeverGuardFlowLayout() //存放每一列的高度 @property (nonatomic, retain) NSMutableArray *columnHeightsArray; //每个section的每一列的高度 @property (nonatomic, retain) NSMutableArray *collectionHeightsArray; //存放每一个cell的属性 @property (nonatomic, retain) NSMutableArray *attributesArray; @end @implementation ForeverGuardFlowLayout /** 每个区的最小高度 @param section 区索引 @return 高度 */ - (CGFloat)minHeightWithSection:(NSInteger)section{ CGFloat min = 1000000; for (NSNumber *height in _collectionHeightsArray[section]) { if (min > [height floatValue]) { min = [height floatValue]; } } return min; } /** 每个区的初始Y坐标 @param section 区索引 @return Y坐标 */ - (CGFloat)maxHeightWithSection:(NSInteger)section{ if (section>0) { CGFloat max = 0; for (int i=0; i<section; i++) { max += [self maxHeightAboutSection:_collectionHeightsArray[i]]; } return max; }else{ return 0; } } /** 每个区的最大高度 @param dataArr 每个区的所有列的高度 @return 最大高度 */ - (CGFloat)maxHeightAboutSection:(NSMutableArray *)dataArr{ CGFloat max = 0; for (NSNumber *heigth in dataArr) { if (max < [heigth floatValue]) { max = [heigth floatValue]; } } return max; } /** collectionView的显示高度 */ - (CGFloat)collectionHeight{ CGFloat max = 0; for (NSMutableArray *sectionArr in _collectionHeightsArray) { max += [self maxHeightAboutSection:sectionArr]; } return max; } /** 当前区的最小高度的索引 @param section 当前区 @return 最小高度的索引 */ - (NSUInteger)indexOfMinHeightWithSection:(NSInteger)section{ NSUInteger index = 0; NSMutableArray *sectionArr = _collectionHeightsArray[section]; for (int i=0; i<sectionArr.count; i++) { CGFloat height = [sectionArr[i] floatValue]; if (height == [self minHeightWithSection:section]) { index = i; return index; } } return index; } /** 重写系统prepareLayout方法 (设置item的坐标等属性) */ - (void)prepareLayout{ [super prepareLayout]; _attributesArray = [[NSMutableArray alloc] init]; _columnHeightsArray = [NSMutableArray arrayWithCapacity:self.numberOfColumn]; NSUInteger sectionCount = [self.collectionView numberOfSections]; _collectionHeightsArray = [NSMutableArray arrayWithCapacity:sectionCount]; for (int index = 0; index<sectionCount; index++) { NSMutableArray *columnArr = [NSMutableArray array]; for (int i=0; i<self.numberOfColumn; i++) { [columnArr addObject:@0.0]; } [_collectionHeightsArray addObject:columnArr]; } CGFloat totalWidth = self.collectionView.frame.size.width; CGFloat x = 0; CGFloat y = 0; for (int index= 0; index<sectionCount; index++) { NSUInteger itemCount = [self.collectionView numberOfItemsInSection:index]; x = 0; y = [self maxHeightWithSection:index]; for (int i=0; i<itemCount; i++) { NSUInteger numberIfSoace = self.numberOfColumn-1; CGFloat spaceWidth = 7.5;//item左右间距 CGFloat width = (totalWidth - spaceWidth*numberIfSoace)/self.numberOfColumn; NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:index]; CGSize imageSize =[self.delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath]; CGFloat height = width * imageSize.height / imageSize.width; UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; attributes.frame = CGRectMake(x, y, width, height); [_attributesArray addObject:attributes]; NSUInteger minHeightIndex = [self indexOfMinHeightWithSection:index]; CGFloat minHeight = [_collectionHeightsArray[index][minHeightIndex] floatValue]; CGFloat lineHeight = 7.5;//item上下间距 _collectionHeightsArray[index][minHeightIndex] = [NSNumber numberWithFloat:minHeight+lineHeight+height]; minHeightIndex = [self indexOfMinHeightWithSection:index]; x = (spaceWidth + width) * minHeightIndex; y = [self minHeightWithSection:index]+[self maxHeightWithSection:index]; } } } /** 返回collectionView的界面显示大小 */ - (CGSize)collectionViewContentSize{ return CGSizeMake(self.collectionView.frame.size.width, [self collectionHeight]); } /** 将所有的layoutAttributes重写布局 */ - (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{ return _attributesArray; } @end
ForeverGuard博客园