本文主要是介绍给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];
}
}