我们有时候会遇到这样的情形,就是需要展示一些动态的标签,宽度是动态的,
水平方向是一行,其实这种情况还是比较容易处理的,只是一下子想不起来,
这里做了一个相关的需求,将思路和代码记录下来,方便后续的查找
效果图
思路:就是重写自定义layout的prepare layout 方法, 在里面计算每一个item 的frame
。通过[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:i inSection:0]] 方法创建 UICollectionViewLayoutAttributes 对象,然后个UICollectionViewLayoutAttributes 对象的frame赋值,这里要记录上一个UICollectionViewLayoutAttributes对象的x.及总的宽度。通过这句代码赋值frame
layoutAttributes.frame = CGRectMake(currentX, currentY, cellWidth, cellHeight);
然后将布局属性添加到一个数组中
在layoutAttributesForElementsInRect:方法中返回数组。
在 collectionViewContentSize 方法中返回宽度
还有一点,我们需要通过代理方式获取到单个item的宽度
-
(CGFloat)cellWidthForItemAtIndex:(NSInteger)index;
-
(CGFloat)footerWidthForFooterAtSection:(NSInteger)section;
代码
@protocol LIUNumberCenterAssociationLayoutDelegate <NSObject>
- (CGFloat)cellWidthForItemAtIndex:(NSInteger)index;
- (CGFloat)footerWidthForFooterAtSection:(NSInteger)section;
@end
@interface LIUNumberCenterAssociationLayout : UICollectionViewFlowLayout
@property (nonatomic, weak) id <LIUNumberCenterAssociationLayoutDelegate> delegate;
@end
//
// LIUNumberCenterAssociationLayout.m
//
#import "LIUNumberCenterAssociationLayout.h"
@interface LIUNumberCenterAssociationLayout ()
@property (nonatomic, strong) NSMutableArray<UICollectionViewLayoutAttributes *> *layoutAttributesArray;
@property (nonatomic, assign) CGSize contentSize;
@end
@implementation LIUNumberCenterAssociationLayout
- (instancetype)init {
if (self = [super init]) {
self.layoutAttributesArray = [NSMutableArray new];
self.contentSize = CGSizeMake(16, 22); // 16是左边距
}
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];
self.contentSize = CGSizeMake(8, 28); // 16是左边距
// 计算新的布局
NSInteger count = 0;
if ([self.collectionView.dataSource respondsToSelector:@selector(collectionView:numberOfItemsInSection:)]) {
count = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:0];
}
CGFloat x = 0;
if (count > 0) {
for (int i = 0; i < count; i++) {
CGFloat currentX = x;
CGFloat currentY = 0;
CGFloat cellWidth = [self cellWidthForItemAtIndex:i];
CGFloat cellHeight = 28;
// 创建布局属性
UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
layoutAttributes.frame = CGRectMake(currentX, currentY, cellWidth, cellHeight);
[self.layoutAttributesArray addObject:layoutAttributes];
// 计算下一个item的x,以及布局更新结束检测
if (i < count - 1) {
x = currentX + cellWidth + 8; // 8是间距
} else {
x = currentX + cellWidth + 8; // 8是右边距
self.contentSize = CGSizeMake(x, 0);
}
}
}
if ([self.delegate respondsToSelector:@selector(footerWidthForFooterAtSection:)]) {
CGFloat footerWidth = [self.delegate footerWidthForFooterAtSection:0];
UICollectionViewLayoutAttributes *layoutattribute = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter withIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
layoutattribute.frame = CGRectMake(x, 0, footerWidth, 28);
x += footerWidth ;
self.contentSize = CGSizeMake(x, 28);
[self.layoutAttributesArray addObject:layoutattribute];
}
}
- (CGFloat)cellWidthForItemAtIndex:(NSInteger)index {
CGFloat width = 0;
if ([self.delegate respondsToSelector:@selector(cellWidthForItemAtIndex:)]) {
width = [self.delegate cellWidthForItemAtIndex:index];
}
return width;
}
@end