在iOS开发中 使用UIcollectionView 处理标签显示的时候 可能会遇到如下问题。
当使用不规则(宽度不一致)的 UIcollectionViewCell 的时候。 会导致每个item的间隔不一致。item会先与父视图左右对齐。
这样的问题就导致 cell之间未按照设定的间距进行显示。
处理方式:自定义 UICollectionViewLeftAlignedLayout : UICollectionViewFlowLayout (来源于网络)
UICollectionViewLeftAlignedLayout.h
#import <UIKit/UIKit.h>
@interface UICollectionViewLeftAlignedLayout : UICollectionViewFlowLayout
@end
@protocol UICollectionViewDelegateLeftAlignedLayout <UICollectionViewDelegateFlowLayout>
@end
UICollectionViewLeftAlignedLayout.m
#import "UICollectionViewLeftAlignedLayout.h"
@interface UICollectionViewLayoutAttributes (LeftAligned)
- (void)leftAlignFrameWithSectionInset:(UIEdgeInsets)sectionInset;
@end
@implementation UICollectionViewLayoutAttributes (LeftAligned)
- (void)leftAlignFrameWithSectionInset:(UIEdgeInsets)sectionInset
{
CGRect frame = self.frame;
frame.origin.x = sectionInset.left;
self.frame = frame;
}
@end
#pragma mark -
@implementation UICollectionViewLeftAlignedLayout
#pragma mark - UICollectionViewLayout
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSArray *originalAttributes = [super layoutAttributesForElementsInRect:rect];
NSMutableArray *updatedAttributes = [NSMutableArray arrayWithArray:originalAttributes];
for (UICollectionViewLayoutAttributes *attributes in originalAttributes) {
if (!attributes.representedElementKind) {
NSUInteger index = [updatedAttributes indexOfObject:attributes];
updatedAttributes[index] = [self layoutAttributesForItemAtIndexPath:attributes.indexPath];
}
}
return updatedAttributes;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes* currentItemAttributes = [[super layoutAttributesForItemAtIndexPath:indexPath] copy];
UIEdgeInsets sectionInset = [self evaluatedSectionInsetForItemAtIndex:indexPath.section];
BOOL isFirstItemInSection = indexPath.item == 0;
CGFloat layoutWidth = CGRectGetWidth(self.collectionView.frame) - sectionInset.left - sectionInset.right;
if (isFirstItemInSection) {
[currentItemAttributes leftAlignFrameWithSectionInset:sectionInset];
return currentItemAttributes;
}
NSIndexPath* previousIndexPath = [NSIndexPath indexPathForItem:indexPath.item-1 inSection:indexPath.section];
CGRect previousFrame = [self layoutAttributesForItemAtIndexPath:previousIndexPath].frame;
CGFloat previousFrameRightPoint = previousFrame.origin.x + previousFrame.size.width;
CGRect currentFrame = currentItemAttributes.frame;
CGRect strecthedCurrentFrame = CGRectMake(sectionInset.left,
currentFrame.origin.y,
layoutWidth,
currentFrame.size.height);
// if the current frame, once left aligned to the left and stretched to the full collection view
// width intersects the previous frame then they are on the same line
BOOL isFirstItemInRow = !CGRectIntersectsRect(previousFrame, strecthedCurrentFrame);
if (isFirstItemInRow) {
// make sure the first item on a line is left aligned
[currentItemAttributes leftAlignFrameWithSectionInset:sectionInset];
return currentItemAttributes;
}
CGRect frame = currentItemAttributes.frame;
frame.origin.x = previousFrameRightPoint + [self evaluatedMinimumInteritemSpacingForSectionAtIndex:indexPath.section];
currentItemAttributes.frame = frame;
return currentItemAttributes;
}
- (CGFloat)evaluatedMinimumInteritemSpacingForSectionAtIndex:(NSInteger)sectionIndex
{
if ([self.collectionView.delegate respondsToSelector:@selector(collectionView:layout:minimumInteritemSpacingForSectionAtIndex:)]) {
id<UICollectionViewDelegateLeftAlignedLayout> delegate = (id<UICollectionViewDelegateLeftAlignedLayout>)self.collectionView.delegate;
return [delegate collectionView:self.collectionView layout:self minimumInteritemSpacingForSectionAtIndex:sectionIndex];
} else {
return self.minimumInteritemSpacing;
}
}
- (UIEdgeInsets)evaluatedSectionInsetForItemAtIndex:(NSInteger)index
{
if ([self.collectionView.delegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)]) {
id<UICollectionViewDelegateLeftAlignedLayout> delegate = (id<UICollectionViewDelegateLeftAlignedLayout>)self.collectionView.delegate;
return [delegate collectionView:self.collectionView layout:self insetForSectionAtIndex:index];
} else {
return self.sectionInset;
}
}
@end
使用自定义 UIcollectionViewLayout解决item标签居左问题。
OC 使用方式
UICollectionViewLeftAlignedLayout *layout = [[UICollectionViewLeftAlignedLayout alloc] init];
layout.minimumLineSpacing = 8;
layout.minimumInteritemSpacing = 8;
layout.sectionInset = UIEdgeInsetsMake(10, 10 ,10, 10);
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
self.mainCollectionView.collectionViewLayout = layout;
Swift 使用
let layout:UICollectionViewLeftAlignedLayout = UICollectionViewLeftAlignedLayout.init()
// layout.minimumLineSpacing = 10
layout.minimumInteritemSpacing = 10
layout.sectionInset = UIEdgeInsets.init(top: 10, left: 0, bottom: 20, right: 13)
self.statusView.collectionViewLayout = layout;
结果:自己验证吧😊