// // KBSvipFlowLayout.m // keyBoard // // SVIP 页面自定义布局,支持 Section 背景装饰视图 // #import "KBSvipFlowLayout.h" #import "KBSvipBenefitBgView.h" static NSString * const kKBSvipDecorationViewKind = @"KBSvipBenefitBgDecoration"; @interface KBSvipFlowLayout () @property (nonatomic, strong) NSMutableArray *decorationAttributes; @end @implementation KBSvipFlowLayout - (instancetype)init { if (self = [super init]) { _decorationSection = 1; // 默认 Section 1 需要背景 [self registerClass:[KBSvipBenefitBgView class] forDecorationViewOfKind:kKBSvipDecorationViewKind]; } return self; } - (void)prepareLayout { [super prepareLayout]; self.decorationAttributes = [NSMutableArray array]; NSInteger numberOfSections = [self.collectionView numberOfSections]; if (self.decorationSection >= numberOfSections) { return; } NSInteger numberOfItems = [self.collectionView numberOfItemsInSection:self.decorationSection]; if (numberOfItems == 0) { return; } // 获取 Section Header 的布局属性 UICollectionViewLayoutAttributes *headerAttr = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathForItem:0 inSection:self.decorationSection]]; // 获取第一个和最后一个 item 的布局属性 UICollectionViewLayoutAttributes *firstItemAttr = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:self.decorationSection]]; UICollectionViewLayoutAttributes *lastItemAttr = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:numberOfItems - 1 inSection:self.decorationSection]]; if (!firstItemAttr || !lastItemAttr) { return; } // 计算背景区域 UIEdgeInsets sectionInset = self.sectionInset; if ([self.collectionView.delegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)]) { sectionInset = [(id)self.collectionView.delegate collectionView:self.collectionView layout:self insetForSectionAtIndex:self.decorationSection]; } CGFloat minY = CGRectGetMinY(headerAttr.frame); CGFloat maxY = CGRectGetMaxY(lastItemAttr.frame) + 16; // 底部留 16 间距 CGFloat x = sectionInset.left; CGFloat width = self.collectionView.bounds.size.width - sectionInset.left - sectionInset.right; CGRect decorationFrame = CGRectMake(x, minY, width, maxY - minY); UICollectionViewLayoutAttributes *decorationAttr = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:kKBSvipDecorationViewKind withIndexPath:[NSIndexPath indexPathForItem:0 inSection:self.decorationSection]]; decorationAttr.frame = decorationFrame; decorationAttr.zIndex = -1; // 放在最底层 [self.decorationAttributes addObject:decorationAttr]; } - (NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect { NSMutableArray *attrs = [[super layoutAttributesForElementsInRect:rect] mutableCopy]; for (UICollectionViewLayoutAttributes *decorationAttr in self.decorationAttributes) { if (CGRectIntersectsRect(rect, decorationAttr.frame)) { [attrs addObject:decorationAttr]; } } return attrs; } - (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath { if ([elementKind isEqualToString:kKBSvipDecorationViewKind]) { for (UICollectionViewLayoutAttributes *attr in self.decorationAttributes) { if (attr.indexPath.section == indexPath.section) { return attr; } } } return [super layoutAttributesForDecorationViewOfKind:elementKind atIndexPath:indexPath]; } @end