CollectionView里的Section分别设置不同的背景色-ObjC

发布于:2025-04-21 ⋅ 阅读:(78) ⋅ 点赞:(0)

本文主要是介绍给UICollectionView 的Section设置不同背景色以及单元格没有cell时也需要填充背景色的场景,原文Swift版请参考 Swift - 让CollectionView里的Section分别设置不同的背景色_fordecorationviewofkind-CSDN博客。由于使用阿里的通义灵码翻译存在错误,因此动手翻译了下,亲测OK,供有需要的同学借鉴,具体参考如下:

SectionBgCollectionViewLayout.h文件

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

//MARK: - SectionBgCollectionViewDelegate
@protocol SectionBgCollectionViewDelegate <UICollectionViewDelegateFlowLayout>

- (UIColor *)collectionView:(UICollectionView *)collectionView
                     layout:(UICollectionViewLayout *)collectionViewLayout
backgroundColorForSectionAt:(NSInteger)section;

@end


/// 自定义Layout
/// https://blog.csdn.net/sundaysme/article/details/81916074/
@interface SectionBgCollectionViewLayout : UICollectionViewFlowLayout

@property (nonatomic, strong) NSDictionary<NSNumber *, NSNumber *> *dicSpaceBetweenColumns;

@end

NS_ASSUME_NONNULL_END

SectionBgCollectionViewLayout.m文件

#import "SectionBgCollectionViewLayout.h"

NSString *const SectionBg = @"SectionBgCollectionReusableView";


//MARK: - SectionBgCollectionViewLayoutAttributes
@interface SectionBgCollectionViewLayoutAttributes : UICollectionViewLayoutAttributes

@property (nonatomic, strong) UIColor *backgroundColor;

@end

@implementation SectionBgCollectionViewLayoutAttributes

- (instancetype)copyWithZone:(NSZone *)zone {
    SectionBgCollectionViewLayoutAttributes *copy = [super copyWithZone:zone];
    copy.backgroundColor = self.backgroundColor;
    return copy;
}

- (BOOL)isEqual:(id)object {
    if (![super isEqual:object]) {
        return NO;
    }
    
    SectionBgCollectionViewLayoutAttributes *rhs = object;
    if (![_backgroundColor isEqual:rhs.backgroundColor]) {
        return NO;
    }
    
    return YES;
}

@end


//MARK: - SectionBgCollectionReusableView
@interface SectionBgCollectionReusableView : UICollectionReusableView

@end

@implementation SectionBgCollectionReusableView

- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
    [super applyLayoutAttributes:layoutAttributes];
    
    SectionBgCollectionViewLayoutAttributes *attr = (SectionBgCollectionViewLayoutAttributes *)layoutAttributes;
    self.backgroundColor = attr.backgroundColor;
}

@end


//MARK: - SectionBgCollectionViewLayout
@implementation SectionBgCollectionViewLayout{
    NSMutableArray<UICollectionViewLayoutAttributes *> *_decorationViewAttrs;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self setup];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
        [self setup];
    }
    return self;
}

- (void)awakeFromNib{
    [super awakeFromNib];
    [self setup];
}

- (void)setup {
    _decorationViewAttrs = [NSMutableArray array];
    [self registerClass:[SectionBgCollectionReusableView class] forDecorationViewOfKind:SectionBg];
}

- (void)prepareLayout{
    [super prepareLayout];
    
    UICollectionView *collectionView = self.collectionView;
    id<SectionBgCollectionViewDelegate> delegate = collectionView.delegate;
    
    if (!collectionView || !delegate) {
        return;
    }
    
    [_decorationViewAttrs removeAllObjects];
    
    NSInteger numberOfSections = collectionView.numberOfSections;
    for (NSInteger section = 0; section < numberOfSections; section++) {
        NSInteger numberOfItems = [collectionView numberOfItemsInSection:section];
        if (numberOfItems == 0) {
            continue;
        }
        
        NSIndexPath *firstIndexPath = [NSIndexPath indexPathForItem:0 inSection:section];
        NSIndexPath *lastIndexPath = [NSIndexPath indexPathForItem:numberOfItems - 1 inSection:section];
        
        UICollectionViewLayoutAttributes *firstItem = [self layoutAttributesForItemAtIndexPath:firstIndexPath];
        UICollectionViewLayoutAttributes *lastItem = [self layoutAttributesForItemAtIndexPath:lastIndexPath];
        
        if (!firstItem || !lastItem) {
            continue;
        }
        
        UIEdgeInsets sectionInset = self.sectionInset;
        if ([delegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)]) {
            sectionInset = [delegate collectionView:collectionView layout:self insetForSectionAtIndex:section];
        }
        
        CGRect sectionFrame = CGRectUnion(firstItem.frame, lastItem.frame);
        sectionFrame.origin.x = sectionInset.left;
        sectionFrame.origin.y -= sectionInset.top;
        
        if (self.scrollDirection == UICollectionViewScrollDirectionHorizontal) {
            sectionFrame.size.height = collectionView.bounds.size.height;
        } else {
            sectionFrame.size.width = collectionView.bounds.size.width - sectionInset.left - sectionInset.right;
            sectionFrame.size.height += sectionInset.top + sectionInset.bottom;
        }
        
        SectionBgCollectionViewLayoutAttributes *attr = [SectionBgCollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:SectionBg withIndexPath:[NSIndexPath indexPathForItem:0 inSection:section]];
        attr.frame = sectionFrame;
        attr.zIndex = -1;
        attr.backgroundColor = [delegate collectionView:collectionView layout:self backgroundColorForSectionAt:section];
        
        [_decorationViewAttrs addObject:attr];
        
    }
}


- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
    NSMutableArray<UICollectionViewLayoutAttributes *> *attrs = [NSMutableArray arrayWithArray:[super layoutAttributesForElementsInRect:rect]];
    
    for (UICollectionViewLayoutAttributes *attr in _decorationViewAttrs) {
        if (CGRectIntersectsRect(rect, attr.frame)) {
            [attrs addObject:attr];
        }
    }
    
    // Adjust column spacing issues
    if (attrs.count > 0) {
        for (NSUInteger i = 1; i < attrs.count; i++) {
            UICollectionViewLayoutAttributes *currentLayoutAttributes = attrs[i];
            UICollectionViewLayoutAttributes *prevLayoutAttributes = attrs[i - 1];
            
            if (currentLayoutAttributes.indexPath.section != prevLayoutAttributes.indexPath.section) {
                continue;
            }
            
            CGFloat maximumSpacing = self.minimumInteritemSpacing;
            if (self.dicSpaceBetweenColumns && self.dicSpaceBetweenColumns[@(currentLayoutAttributes.indexPath.section)]) {
                maximumSpacing = [self.dicSpaceBetweenColumns[@(currentLayoutAttributes.indexPath.section)] floatValue];
            }
            
            UIEdgeInsets sectionInset = self.sectionInset;
            if([self.collectionView.delegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)]){
                id<SectionBgCollectionViewDelegate> delegate = self.collectionView.delegate;
                sectionInset = [delegate collectionView:self.collectionView
                                                 layout:self
                                 insetForSectionAtIndex:currentLayoutAttributes.indexPath.section];
            }
            
            CGFloat origin = CGRectGetMaxX(prevLayoutAttributes.frame);
            CGRect frame = currentLayoutAttributes.frame;
            if ((origin + maximumSpacing + currentLayoutAttributes.frame.size.width) <= self.collectionViewContentSize.width) {
                frame.origin.x = origin + maximumSpacing;
            } else {
                frame.origin.x = sectionInset.left;
            }
            currentLayoutAttributes.frame = frame;
        }
    }
    
    return attrs;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath {
    if ([elementKind isEqualToString:SectionBg]) {
        return _decorationViewAttrs[indexPath.section];
    }
    
    return [super layoutAttributesForDecorationViewOfKind:elementKind atIndexPath:indexPath];
}

@end

使用参考:

一:使用SectionBgCollectionViewLayout

//        UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
        //        layout.scrollDirection = UICollectionViewScrollDirectionVertical;
        
        SectionBgCollectionViewLayout *layout = [[SectionBgCollectionViewLayout alloc] init];
        layout.scrollDirection = UICollectionViewScrollDirectionVertical;
        layout.dicSpaceBetweenColumns = @{
            @0:@0,
            @1:_topMenuOrdes > 1 ? @8.5 : @0,
            @2:@0,
            @3:@0,
            @4:@0,
            @5:@0
        };
        collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero
                                             collectionViewLayout:layout];

dicSpaceBetweenColumns 主要是设置列间距,minimumInteritemSpacingForSectionAtIndex 委托方法直接返回0 。  

二:实现DFServiceMenuEditViewDelegate协议中的backgroundColorForSectionAt方法设置对应背景色即可:

//MARK: - SectionBgCollectionViewDelegate
- (UIColor *)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout backgroundColorForSectionAt:(NSInteger)section{
    switch (section) {
        case 5:
            return [UIColor whiteColor];
            
        default:
            return [UIColor clearColor];
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到