首先看效果图
实现的思路,支持配置代理,通过代理方式设置
每个item的frame,支持设置头部的size,
支持多个分区,之前做过类似的,但是只支持一个分区,
后来遇到过几次多分区的,都是将一个collectionView放到tableViewCell 中实现的,这次为了使layout更强大,支持了多
个分区的,思路就是我们在prepare layout 获取到
分区数量和每个分区cell数量
,然后创建对应的布局属性,添加到一个总的数组中
然后在系统方法中返回整个数组即可
//
// LBMutilMutilAutoWidthLayout.m
// TEXT
//
// Created by mac on 2025/3/30.
//#import "LBMutilMutilAutoWidthLayout.h"@interface LBMutilMutilAutoWidthLayout ()@property (nonatomic, strong) NSMutableArray<UICollectionViewLayoutAttributes *> *layoutAttributesArray;@property (nonatomic, assign) CGSize contentSize;@end@implementation LBMutilMutilAutoWidthLayout- (instancetype)init {if (self = [super init]) {self.layoutAttributesArray = [NSMutableArray new];}return self;
}- (void)prepareLayout {[super prepareLayout];[self updateLayout];
}- (CGSize)collectionViewContentSize {return self.contentSize;
}- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {return self.layoutAttributesArray;
}#pragma mark - ---------- update ----------- (void)updateLayout {// 移除旧的布局[self.layoutAttributesArray removeAllObjects];CGFloat currentY = 0;CGFloat x = self.sectionInset.left;// 计算新的布局NSInteger sectionCount = [self.collectionView numberOfSections];for (int i = 0; i < sectionCount; i ++) {CGSize headerSize = CGSizeZero;if (self.delegate && [self.delegate respondsToSelector:@selector(sizeForHeaderViewAtSection:)]) {headerSize = [self.delegate sizeForHeaderViewAtSection:i];}if (!CGSizeEqualToSize(headerSize, CGSizeZero)) {UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader withIndexPath:[NSIndexPath indexPathForItem:0 inSection:i]];;layoutAttributes.frame = CGRectMake(0, currentY, headerSize.width, headerSize.height);currentY += headerSize.height;[self.layoutAttributesArray addObject:layoutAttributes];}NSInteger count = 0;if ([self.collectionView.dataSource respondsToSelector:@selector(collectionView:numberOfItemsInSection:)]) {count = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:0];}CGFloat currentX = x;if (count > 0) {for (int j = 0; j < count; j++) {CGSize cellSize = [self sizeForItemAtIndexPath:[NSIndexPath indexPathForItem:j inSection:i]];CGFloat cellWidth = cellSize.width;CGFloat cellHeight = cellSize.height;// 创建布局属性UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:j inSection:i]];layoutAttributes.frame = CGRectMake(currentX, currentY, cellWidth, cellHeight);[self.layoutAttributesArray addObject:layoutAttributes];currentX += (self.minimumInteritemSpacing + cellWidth);// 计算下一个item的x,以及布局更新结束检测if (j != count - 1) {if (currentX + cellWidth + self.minimumInteritemSpacing + self.sectionInset.right > self.contentWidth) {currentX = self.sectionInset.left;currentY += self.minimumLineSpacing + cellHeight;}} else {currentY += cellHeight;}if (i == sectionCount - 1 && j == count - 1) {self.contentSize = CGSizeMake(self.contentWidth, currentY);}}}}
}- (CGSize)sizeForItemAtIndexPath:(NSIndexPath *)index {CGSize size = CGSizeZero;if ([self.delegate respondsToSelector:@selector(sizeForItemAtIndexPath:)]) {size = [self.delegate sizeForItemAtIndexPath:index];}return size;
}@end
用法
//
// LBMutilSecionAutoLayoutViewController.m
// TEXT
//
// Created by mac on 2025/3/30.
//#import "LBMutilSecionAutoLayoutViewController.h"
#import "LBMutilMutilAutoWidthLayout.h"@interface LBMutilSecionAutoLayoutViewController () <LBMutilMutilAutoWidthLayouttDelegate,
UICollectionViewDelegate,
UICollectionViewDataSource>@property (nonatomic, strong) UICollectionView *collectionView;@end@implementation LBMutilSecionAutoLayoutViewController- (void)viewDidLoad {[super viewDidLoad];[self.view addSubview:self.collectionView];// Do any additional setup after loading the view.
}#pragma mark - UICollectionViewDelegate,UICollectionViewDataSource- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"22" forIndexPath:indexPath];cell.contentView.backgroundColor = [UIColor cyanColor];return cell;
}- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{UICollectionReusableView *header = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"header" forIndexPath:indexPath];return header;
}- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{return 3;
}- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{return 10;
}
#pragma mark - LBMutilMutilAutoWidthLayouttDelegate- (CGSize)sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{CGFloat width;if (indexPath.section == 0) {width = 100;if (indexPath.item %2 == 0) {width = 50;}} else {width = 70;if (indexPath.item %2 == 0) {width = 30;}}return CGSizeMake(width, 20);
}- (CGSize)sizeForHeaderViewAtSection:(NSInteger)section
{return CGSizeMake(375, 40);
}#pragma mark - lazy load- (UICollectionView *)collectionView
{if (!_collectionView) {LBMutilMutilAutoWidthLayout *layout = [[LBMutilMutilAutoWidthLayout alloc] init];layout.delegate = self;layout.contentWidth = 375;layout.minimumInteritemSpacing = 10;layout.sectionInset = UIEdgeInsetsZero;_collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 100, 375, 400) collectionViewLayout:layout];_collectionView.dataSource = self;_collectionView.delegate = self;[_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"22"];[_collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"];}return _collectionView;
}@end