139 lines
5.2 KiB
Objective-C
139 lines
5.2 KiB
Objective-C
//
|
||
// MSSessionScrollingItemFlowLayout.m
|
||
// YuMi
|
||
//
|
||
// Created by duoban on 2024/5/11.
|
||
//
|
||
|
||
#import "MSSessionScrollingItemFlowLayout.h"
|
||
@interface MSSessionScrollingItemFlowLayout()
|
||
@property (nonatomic, strong) NSMutableArray *itemAttributes; // 存放每个cell的布局属性
|
||
|
||
// 垂直瀑布流相关属性
|
||
@property (nonatomic, strong) NSMutableArray *columnsHeights; // 每一列的高度(count=多少列)
|
||
@property (nonatomic, assign) CGFloat maxHeight; // 最长列的高度(最大高度)
|
||
@property (nonatomic, assign) CGFloat minHeight; // 最短列的高度(最低高度)
|
||
@property (nonatomic, assign) NSInteger minIndex; // 最短列的下标
|
||
@property (nonatomic, assign) NSInteger maxIndex; // 最长列的下标
|
||
|
||
// 水平瀑布流相关属性
|
||
@property (nonatomic, strong) NSMutableArray *columnsWidths; // 每一行的宽度(count不确定)
|
||
@property (nonatomic, assign) NSInteger tempItemX; // 临时x : 用来计算每个cell的x值
|
||
@property (nonatomic, assign) NSInteger maxRowIndex; //最大行
|
||
@end
|
||
@implementation MSSessionScrollingItemFlowLayout
|
||
//
|
||
#pragma mark -- 系统内部方法
|
||
/**
|
||
* 重写父类布局
|
||
*/
|
||
- (void)prepareLayout {
|
||
|
||
[super prepareLayout];
|
||
// (水平瀑布流时)重置最大行
|
||
if ((self.type == MSDirectionTypeHorizontalType)) {
|
||
self.maxRowIndex = 0;
|
||
}
|
||
|
||
if (self.type == MSDirectionTypeVerticalType) {
|
||
// (垂直瀑布流时)重置每一列的高度
|
||
[self.columnsHeights removeAllObjects];
|
||
for (NSUInteger i = 0; i < self.numberOfColumns; i++) {
|
||
[self.columnsHeights addObject:@(self.insets.top)];
|
||
}
|
||
}
|
||
|
||
// 计算所有cell的布局属性
|
||
[self.itemAttributes removeAllObjects];
|
||
NSUInteger itemCount = [self.collectionView numberOfItemsInSection:0];
|
||
self.tempItemX = self.insets.left;
|
||
for (NSUInteger i = 0; i < itemCount; ++i) {
|
||
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
|
||
if (self.type == MSDirectionTypeVerticalType) {
|
||
[self setVerticalFrame:indexPath];
|
||
}else if ((self.type == MSDirectionTypeHorizontalType)){
|
||
[self setHorizontalFrame:indexPath];
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 水平瀑布:设置每一个attrs的frame,并加入数组中
|
||
*/
|
||
- (void)setHorizontalFrame:(NSIndexPath *)indexPath {
|
||
UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
|
||
CGFloat w = [self.itemWidths[indexPath.item] floatValue];
|
||
CGFloat width = w + self.columnGap;
|
||
CGFloat h = (self.rowHeight == 0) ? 100 : self.rowHeight;
|
||
|
||
/**
|
||
* 如果当前的x值+当前cell的宽度 超出了 屏幕宽度,那么就要换行了。
|
||
* 换行操作 : 最大行+1,tempItemX重置为10(self.insets.left)。
|
||
*/
|
||
if (self.tempItemX + w > [UIScreen mainScreen].bounds.size.width) {
|
||
self.maxRowIndex++;
|
||
self.tempItemX = self.insets.left;
|
||
}
|
||
CGFloat x = self.tempItemX;
|
||
CGFloat y = self.insets.top + self.maxRowIndex * (h + self.rowGap);
|
||
attrs.frame = CGRectMake(x, y, w, h);
|
||
|
||
/**
|
||
* 注:1.cell的宽度和高度算起来比较简单 : 宽度由外部传进来,高度固定为rowHeight(默认为100)。
|
||
* 2.cell的x : 通过tempItemX算好了。
|
||
* 3.cell的y : minHeight最短列的高度,也就是最低高度,作为当前cell的起始y,当然要加上行之间的间隙。
|
||
*/
|
||
|
||
NSLog(@"%@",NSStringFromCGRect(attrs.frame));
|
||
[self.itemAttributes addObject:attrs];
|
||
self.tempItemX += width;
|
||
}
|
||
|
||
/**
|
||
* 垂直瀑布:设置每一个attrs的frame,并加入数组中
|
||
*/
|
||
- (void)setVerticalFrame:(NSIndexPath *)indexPath {
|
||
UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
|
||
|
||
// cell的frame
|
||
CGFloat w = self.itemWidth;
|
||
CGFloat h = [self.itemHeights[indexPath.item] floatValue];
|
||
CGFloat x = self.insets.left + self.minIndex * (w + self.columnGap);
|
||
CGFloat y = self.minHeight + self.rowGap;
|
||
attrs.frame = CGRectMake(x, y, w, h);
|
||
|
||
/**
|
||
* 注:1.cell的宽度和高度算起来比较简单 : 宽度固定(itemWidth已经算好),高度由外部传进来
|
||
* 2.cell的x : minIndex最短列作为当前列。
|
||
* 3.cell的y : minHeight最短列的高度,也就是最低高度,作为当前cell的起始y,当然要加上行之间的间隙。
|
||
*/
|
||
|
||
// 更新数组中的最大高度
|
||
self.columnsHeights[self.minIndex] = @(CGRectGetMaxY(attrs.frame));
|
||
NSLog(@"%@",NSStringFromCGRect(attrs.frame));
|
||
[self.itemAttributes addObject:attrs];
|
||
}
|
||
|
||
/**
|
||
* 返回collectionView的尺寸
|
||
*/
|
||
- (CGSize)collectionViewContentSize {
|
||
CGFloat height;
|
||
if (self.type == MSDirectionTypeHorizontalType) {
|
||
CGFloat rowHeight = (self.rowHeight == 0) ? 100 : self.rowHeight;
|
||
height = self.insets.top + (self.maxRowIndex+1) * (rowHeight + self.rowGap);
|
||
}else {
|
||
height = self.maxHeight;
|
||
}
|
||
return CGSizeMake(self.collectionView.frame.size.width, height);
|
||
}
|
||
|
||
/**
|
||
* 所有元素(比如cell、补充控件、装饰控件)的布局属性
|
||
*/
|
||
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
|
||
{
|
||
return self.itemAttributes;
|
||
}
|
||
@end
|