支持多分区的动态自适应宽度layout,完善了之前只支持一个分区的布局,这里直接上代码,可以用来在商品sku, 搜索记录,编辑tab等场景的使用,灵活性强,支持代理配置
//
// LBNumberCenterEditTabLayout.m
//
// Created by liubo on 26.3.25.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@protocol LBNumberCenterEditTabLayout.mDelegate <NSObject>
- (CGSize)sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
- (CGSize)sizeForHeaderViewAtSection:(NSInteger)section;
@end
@interface LBNumberCenterEditTabLayout.m : UICollectionViewFlowLayout
@property (nonatomic, weak) id <LIVNumberCenterEditTabLayoutDelegate> delegate;
@property (nonatomic, assign) CGFloat contentWidth;
@end
NS_ASSUME_NONNULL_END
//
// LBNumberCenterEditTabLayout.m
//
//
// Created by liubo on 26.3.25.
//
#import "LBNumberCenterEditTabLayout.m"
@interface LBNumberCenterEditTabLayout.m ()
@property (nonatomic, strong) NSMutableArray<UICollectionViewLayoutAttributes *> *layoutAttributesArray;
@property (nonatomic, assign) CGSize contentSize;
@end
@implementation LBNumberCenterEditTabLayout.m
- (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