首先你需要自定义这几个类
自定义flowLayout
重写几个方法:
- (instancetype)init
- (void)prepareLayout
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
在我们自定义的flowlayout里需要自定义一个协议这样外部就能穿入一些东西来帮助我们设置组的背景view各种属性
@protocol JHCollectionViewDelegateFlowLayout
- (UIColor *)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout backgroundColorForSection:(NSInteger)section;
@end
在prepare方法里可以看到调用这个方法。
init
初始化一些属性,或者注册我们要设置的组背景。
NSString *const JHCollectionViewSectionBackground = @"JHCollectionViewSectionBackground";
@implementation JHCollectionViewFlowLayout
- (instancetype)init
{
self = [super init];
if (self) {
self.decorationViewAttrs = [NSMutableArray array];
[self setup];
}
return self;
}
- (void)setup
{
[self registerClass:[JHCollectionReusableView class] forDecorationViewOfKind:JHCollectionViewSectionBackground];
}
prepareLayout
这个方法是准备所有view的layoutAttribute信息。
这里设置组背景色的思路是在这里创建一个view去显示颜色,因为这个方法里能拿到所有cell的frame,继而可以拿到组的frame。
[super prepareLayout];
[self.decorationViewAttrs removeAllObjects];
NSInteger numberOfSections = [self.collectionView numberOfSections];
id delegate = self.collectionView.delegate;
if (!numberOfSections || ![delegate conformsToProtocol:@protocol(JHCollectionViewDelegateFlowLayout)]) {
return;
}
for (NSInteger section = 0; section < numberOfSections; section++) {
NSInteger numberOfItems = [self.collectionView numberOfItemsInSection:section];
if (numberOfItems <= 0) {
continue;
}
UICollectionViewLayoutAttributes *firstItem = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:section]];
UICollectionViewLayoutAttributes *lastItem = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:numberOfItems - 1 inSection:section]];
if (!firstItem || !lastItem) {
continue;
}
UIEdgeInsets sectionInset = [self sectionInset];
if ([delegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)]) {
UIEdgeInsets inset = [delegate collectionView:self.collectionView layout:self insetForSectionAtIndex:section];
sectionInset = inset;
}
CGRect sectionFrame = CGRectUnion(firstItem.frame, lastItem.frame);
sectionFrame.origin.x -= sectionInset.left;
sectionFrame.origin.y -= sectionInset.top;
if (self.scrollDirection == UICollectionViewScrollDirectionHorizontal) {
sectionFrame.size.width += sectionInset.left + sectionInset.right;
sectionFrame.size.height = self.collectionView.frame.size.height;
} else {
sectionFrame.size.width = self.collectionView.frame.size.width;
sectionFrame.size.height += sectionInset.top + sectionInset.bottom;
}
// 2、定义
JHCollectionViewLayoutAttributes *attr = [JHCollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:JHCollectionViewSectionBackground withIndexPath:[NSIndexPath indexPathForItem:0 inSection:section]];
attr.frame = sectionFrame;
attr.zIndex = -1;
attr.backgroundColor = [delegate collectionView:self.collectionView layout:self backgroundColorForSection:section];
[self.decorationViewAttrs addObject:attr];
}
我们可以给这个JHCollectionViewLayoutAttributes设置更多属性,不止是backgroundColor
#import <UIKit/UIKit.h>
@interface JHCollectionViewLayoutAttributes : UICollectionViewLayoutAttributes
@property (nonatomic, strong) UIColor *backgroundColor;
@end
比如说圆角属性,可以在这里写。
我们用来设置背景色的view,是自定义的UICollectionReusableView
JHCollectionReusableView
@implementation JHCollectionReusableView
- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
{
[super applyLayoutAttributes:layoutAttributes];
if ([layoutAttributes isKindOfClass:[JHCollectionViewLayoutAttributes class]]) {
JHCollectionViewLayoutAttributes *attr = (JHCollectionViewLayoutAttributes *)layoutAttributes;
self.backgroundColor = attr.backgroundColor;
}
}
@end
在这个方法里拿到所有在prepare方法里设置的attr的属性,然后进行设置即可。
flowlayout补充方法
在flowlayout.m里通常还会重写这几个方法
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
返回在可见区域的view的layoutAttribute信息,
这个方法不写 集合视图显示不出来,这个方法是将保存的每个item的信息告诉集合视图,进行显示。
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSMutableArray *attrs = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
for (UICollectionViewLayoutAttributes *attr in self.decorationViewAttrs) {
if (CGRectIntersectsRect(rect, attr.frame)) {
[attrs addObject:attr];
}
}
return attrs;
}
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString*)elementKind atIndexPath:(NSIndexPath *)indexPath
{
if ([elementKind isEqualToString:JHCollectionViewSectionBackground]) {
return [self.decorationViewAttrs objectAtIndex:indexPath.section];
}
return [super layoutAttributesForDecorationViewOfKind:elementKind atIndexPath:indexPath];
}
参考
https://www.jianshu.com/p/97e930658671