美文网首页iOS程序员的业余沙龙
UICollectionView设置section区域的背景颜色

UICollectionView设置section区域的背景颜色

作者: simliu | 来源:发表于2017-08-31 14:05 被阅读567次

基本思路

1、继承UICollectionViewFlowLayout,在prepareLayout中计算每个section的大小,并存在有sectionBgColor的decoration UICollectionViewLayoutAttributes中。
2、在布局方法layoutAttributesForElementsInRect中,显示屏幕中的attributes

UICollectionSectionColorLayout.h

@protocol UICollectionSectionColorLayout <UICollectionViewDelegateFlowLayout>
@optional
- (UIColor *)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout backgroundColorForSection:(NSInteger)section;
@end

@interface UICollectionSectionColorLayout : UICollectionViewFlowLayout
@end

UICollectionSectionColorLayout.m

#import "UICollectionSectionColorLayout.h"

#define kDecorationReuseIdentifier @"kUICollectionSectionColorIdentifier"

@interface UICollectionSectionColorLayoutAttributes : UICollectionViewLayoutAttributes

@property (nonatomic, strong) UIColor *sectionBgColor;

@end

@implementation UICollectionSectionColorLayoutAttributes

@end

@interface UICollectionSectionColorReusableView : UICollectionReusableView

@end

@implementation UICollectionSectionColorReusableView

- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
{
    [super applyLayoutAttributes:layoutAttributes];
    if ([layoutAttributes isKindOfClass:[UICollectionSectionColorLayoutAttributes class]]) {
        self.backgroundColor = [(UICollectionSectionColorLayoutAttributes *)layoutAttributes sectionBgColor];
    }
}

@end

@interface UICollectionSectionColorLayout (){
    NSMutableArray *_decorationViewAttrs;
}

@end

@implementation UICollectionSectionColorLayout

- (void)prepareLayout
{
    [super prepareLayout];
    
    NSInteger numberOfSections = self.collectionView.numberOfSections;
    if (numberOfSections == 0) {
        return;
    }
    
    [self registerClass:[UICollectionSectionColorReusableView class] forDecorationViewOfKind:kDecorationReuseIdentifier];
    
    if (!_decorationViewAttrs) {
        _decorationViewAttrs = [NSMutableArray array];
    }
    else{
        [_decorationViewAttrs removeAllObjects];
    }
    
    for (int i = 0; i < numberOfSections; i++) {
        NSInteger numberOfItems = [self.collectionView numberOfItemsInSection:i];
        if (numberOfItems == 0 || ![self.collectionView.delegate conformsToProtocol:@protocol(UICollectionSectionColorLayout)]) {
            continue;
        }
        
        UICollectionViewLayoutAttributes *firstAttr = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:i]];
        UICollectionViewLayoutAttributes *lastAttr = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForRow:numberOfItems-1 inSection:i]];
        CGRect sectionFrame = CGRectUnion(firstAttr.frame, lastAttr.frame);
        sectionFrame.origin.x -= self.sectionInset.left;
        sectionFrame.origin.y -= self.sectionInset.top;
        if (self.scrollDirection == UICollectionViewScrollDirectionHorizontal) {
            sectionFrame.size.width += self.sectionInset.left + self.sectionInset.right;
            sectionFrame.size.height = self.collectionView.frame.size.height;
        }
        else{
            sectionFrame.size.width = self.collectionView.frame.size.width;
            sectionFrame.size.height += self.sectionInset.top + self.sectionInset.bottom;
        }
        
        UICollectionSectionColorLayoutAttributes *decorationAttributes =
        [UICollectionSectionColorLayoutAttributes layoutAttributesForDecorationViewOfKind:kDecorationReuseIdentifier
                                                                            withIndexPath:[NSIndexPath indexPathForRow:0 inSection:i]];
        decorationAttributes.frame = sectionFrame;
        decorationAttributes.zIndex = -1;
        UIColor *sectionBgColor = nil;
        if ([self.collectionView.delegate respondsToSelector:@selector(collectionView:layout:backgroundColorForSection:)]) {
            id<UICollectionSectionColorLayout> delegate = (id<UICollectionSectionColorLayout>)self.collectionView.delegate;
            sectionBgColor = [delegate collectionView:self.collectionView layout:self backgroundColorForSection:i];
        }
        decorationAttributes.sectionBgColor = sectionBgColor;
        [_decorationViewAttrs addObject:decorationAttributes];
    }
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
    NSArray *attributes = [super layoutAttributesForElementsInRect:rect];
    NSMutableArray *allAttributes = [NSMutableArray arrayWithArray:attributes];
    for (UICollectionSectionColorLayoutAttributes *attr in _decorationViewAttrs) {
        if (CGRectIntersectsRect(rect, attr.frame)) {
            [allAttributes addObject:attr];
        }
    }
    
    return allAttributes;
}
@end

相关文章

网友评论

  • 毕小强:有bug,如果sectioninset是通过协议实现不是通过设置实现的,背景图frame计算会出问题,应该判断是否实现了collectionView:layout:insetForSectionAtIndex:方法,如果实现,通过协议方法返回的UIEdgeInsets值来计算背景frame

本文标题:UICollectionView设置section区域的背景颜色

本文链接:https://www.haomeiwen.com/subject/yhkqjxtx.html