1
This commit is contained in:
@@ -12,6 +12,8 @@
|
|||||||
- (instancetype)initWithFrame:(CGRect)frame {
|
- (instancetype)initWithFrame:(CGRect)frame {
|
||||||
if (self = [super initWithFrame:frame]) {
|
if (self = [super initWithFrame:frame]) {
|
||||||
self.backgroundColor = [UIColor colorWithHex:0xF6F7FB];
|
self.backgroundColor = [UIColor colorWithHex:0xF6F7FB];
|
||||||
|
// self.backgroundColor = [UIColor redColor];
|
||||||
|
|
||||||
self.layer.cornerRadius = 15;
|
self.layer.cornerRadius = 15;
|
||||||
self.layer.masksToBounds = YES;
|
self.layer.masksToBounds = YES;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,34 @@
|
|||||||
// KBSvipFlowLayout.m
|
// KBSvipFlowLayout.m
|
||||||
// keyBoard
|
// keyBoard
|
||||||
//
|
//
|
||||||
// SVIP 页面自定义布局,支持 Section 背景装饰视图
|
// SVIP 页面自定义布局,支持多个 Section 背景装饰视图
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "KBSvipFlowLayout.h"
|
#import "KBSvipFlowLayout.h"
|
||||||
#import "KBSvipBenefitBgView.h"
|
#import "KBSvipBenefitBgView.h"
|
||||||
|
|
||||||
static NSString * const kKBSvipDecorationViewKind = @"KBSvipBenefitBgDecoration";
|
static NSString * const kKBSvipOuterBgKind = @"KBSvipOuterBgDecoration"; // 外层大背景(18圆角,包裹全部)
|
||||||
|
static NSString * const kKBSvipBenefitBgKind = @"KBSvipBenefitBgDecoration"; // 内层权益背景(15圆角)
|
||||||
|
|
||||||
|
#pragma mark - 外层大背景视图(18圆角,包裹订阅选项+权益列表)
|
||||||
|
|
||||||
|
@interface KBSvipOuterBgView : UICollectionReusableView
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation KBSvipOuterBgView
|
||||||
|
|
||||||
|
- (instancetype)initWithFrame:(CGRect)frame {
|
||||||
|
if (self = [super initWithFrame:frame]) {
|
||||||
|
self.backgroundColor = [UIColor whiteColor];
|
||||||
|
self.layer.cornerRadius = 18;
|
||||||
|
self.layer.masksToBounds = YES;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#pragma mark - KBSvipFlowLayout
|
||||||
|
|
||||||
@interface KBSvipFlowLayout ()
|
@interface KBSvipFlowLayout ()
|
||||||
@property (nonatomic, strong) NSMutableArray<UICollectionViewLayoutAttributes *> *decorationAttributes;
|
@property (nonatomic, strong) NSMutableArray<UICollectionViewLayoutAttributes *> *decorationAttributes;
|
||||||
@@ -18,8 +39,9 @@ static NSString * const kKBSvipDecorationViewKind = @"KBSvipBenefitBgDecoration"
|
|||||||
|
|
||||||
- (instancetype)init {
|
- (instancetype)init {
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
_decorationSection = 1; // 默认 Section 1 需要背景
|
_decorationSection = 1; // Section 1 是权益列表
|
||||||
[self registerClass:[KBSvipBenefitBgView class] forDecorationViewOfKind:kKBSvipDecorationViewKind];
|
[self registerClass:[KBSvipOuterBgView class] forDecorationViewOfKind:kKBSvipOuterBgKind];
|
||||||
|
[self registerClass:[KBSvipBenefitBgView class] forDecorationViewOfKind:kKBSvipBenefitBgKind];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -30,38 +52,61 @@ static NSString * const kKBSvipDecorationViewKind = @"KBSvipBenefitBgDecoration"
|
|||||||
self.decorationAttributes = [NSMutableArray array];
|
self.decorationAttributes = [NSMutableArray array];
|
||||||
|
|
||||||
NSInteger numberOfSections = [self.collectionView numberOfSections];
|
NSInteger numberOfSections = [self.collectionView numberOfSections];
|
||||||
if (self.decorationSection >= numberOfSections) { return; }
|
if (numberOfSections < 2) { return; }
|
||||||
|
|
||||||
NSInteger numberOfItems = [self.collectionView numberOfItemsInSection:self.decorationSection];
|
NSInteger itemCount0 = [self.collectionView numberOfItemsInSection:0];
|
||||||
if (numberOfItems == 0) { return; }
|
NSInteger itemCount1 = [self.collectionView numberOfItemsInSection:1];
|
||||||
|
if (itemCount0 == 0 || itemCount1 == 0) { return; }
|
||||||
|
|
||||||
// 获取 Section Header 的布局属性
|
// 获取 Section 0 第一个 item
|
||||||
UICollectionViewLayoutAttributes *headerAttr = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathForItem:0 inSection:self.decorationSection]];
|
UICollectionViewLayoutAttributes *firstItemAttr = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
|
||||||
|
// 获取 Section 1 Header
|
||||||
|
UICollectionViewLayoutAttributes *benefitHeaderAttr = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathForItem:0 inSection:1]];
|
||||||
|
// 获取 Section 1 最后一个 item
|
||||||
|
UICollectionViewLayoutAttributes *lastBenefitAttr = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:itemCount1 - 1 inSection:1]];
|
||||||
|
|
||||||
// 获取第一个和最后一个 item 的布局属性
|
if (!firstItemAttr || !benefitHeaderAttr || !lastBenefitAttr) { return; }
|
||||||
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 sectionInset0 = [self insetForSection:0];
|
||||||
|
UIEdgeInsets sectionInset1 = [self insetForSection:1];
|
||||||
|
|
||||||
// 计算背景区域
|
// 1. 外层大背景(18圆角):从 Section 0 顶部到 Section 1 底部
|
||||||
UIEdgeInsets sectionInset = self.sectionInset;
|
{
|
||||||
if ([self.collectionView.delegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)]) {
|
CGFloat minY = CGRectGetMinY(firstItemAttr.frame) - sectionInset0.top;
|
||||||
sectionInset = [(id<UICollectionViewDelegateFlowLayout>)self.collectionView.delegate collectionView:self.collectionView layout:self insetForSectionAtIndex:self.decorationSection];
|
CGFloat maxY = CGRectGetMaxY(lastBenefitAttr.frame) + 16;
|
||||||
|
CGFloat x = sectionInset0.left;
|
||||||
|
CGFloat width = self.collectionView.bounds.size.width - sectionInset0.left - sectionInset0.right;
|
||||||
|
|
||||||
|
CGRect frame = CGRectMake(x, minY, width, maxY - minY);
|
||||||
|
|
||||||
|
UICollectionViewLayoutAttributes *attr = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:kKBSvipOuterBgKind withIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
|
||||||
|
attr.frame = frame;
|
||||||
|
attr.zIndex = -2; // 最底层
|
||||||
|
[self.decorationAttributes addObject:attr];
|
||||||
}
|
}
|
||||||
|
|
||||||
CGFloat minY = CGRectGetMinY(headerAttr.frame);
|
// 2. 内层权益背景(15圆角):从 Section 1 Header 到 Section 1 底部,左右距离外层 8px
|
||||||
CGFloat maxY = CGRectGetMaxY(lastItemAttr.frame) + 16; // 底部留 16 间距
|
{
|
||||||
CGFloat x = sectionInset.left;
|
CGFloat minY = CGRectGetMinY(benefitHeaderAttr.frame);
|
||||||
CGFloat width = self.collectionView.bounds.size.width - sectionInset.left - sectionInset.right;
|
CGFloat maxY = CGRectGetMaxY(lastBenefitAttr.frame) + 16;
|
||||||
|
CGFloat x = sectionInset0.left + 8; // 距离外层左边 8px
|
||||||
|
CGFloat width = self.collectionView.bounds.size.width - sectionInset0.left - sectionInset0.right - 16; // 左右各 8px
|
||||||
|
|
||||||
CGRect decorationFrame = CGRectMake(x, minY, width, maxY - minY);
|
CGRect frame = CGRectMake(x, minY, width, maxY - minY);
|
||||||
|
|
||||||
UICollectionViewLayoutAttributes *decorationAttr = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:kKBSvipDecorationViewKind withIndexPath:[NSIndexPath indexPathForItem:0 inSection:self.decorationSection]];
|
UICollectionViewLayoutAttributes *attr = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:kKBSvipBenefitBgKind withIndexPath:[NSIndexPath indexPathForItem:0 inSection:1]];
|
||||||
decorationAttr.frame = decorationFrame;
|
attr.frame = frame;
|
||||||
decorationAttr.zIndex = -1; // 放在最底层
|
attr.zIndex = -1; // 在外层背景之上
|
||||||
|
[self.decorationAttributes addObject:attr];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[self.decorationAttributes addObject:decorationAttr];
|
- (UIEdgeInsets)insetForSection:(NSInteger)section {
|
||||||
|
UIEdgeInsets sectionInset = self.sectionInset;
|
||||||
|
if ([self.collectionView.delegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)]) {
|
||||||
|
sectionInset = [(id<UICollectionViewDelegateFlowLayout>)self.collectionView.delegate collectionView:self.collectionView layout:self insetForSectionAtIndex:section];
|
||||||
|
}
|
||||||
|
return sectionInset;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
|
- (NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
|
||||||
@@ -77,11 +122,9 @@ static NSString * const kKBSvipDecorationViewKind = @"KBSvipBenefitBgDecoration"
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath {
|
- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath {
|
||||||
if ([elementKind isEqualToString:kKBSvipDecorationViewKind]) {
|
for (UICollectionViewLayoutAttributes *attr in self.decorationAttributes) {
|
||||||
for (UICollectionViewLayoutAttributes *attr in self.decorationAttributes) {
|
if ([attr.representedElementKind isEqualToString:elementKind] && attr.indexPath.section == indexPath.section) {
|
||||||
if (attr.indexPath.section == indexPath.section) {
|
return attr;
|
||||||
return attr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [super layoutAttributesForDecorationViewOfKind:elementKind atIndexPath:indexPath];
|
return [super layoutAttributesForDecorationViewOfKind:elementKind atIndexPath:indexPath];
|
||||||
|
|||||||
@@ -78,7 +78,8 @@ static NSString * const kKBSvipBenefitHeaderId = @"kKBSvipBenefitHeaderId";
|
|||||||
}];
|
}];
|
||||||
|
|
||||||
[self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.left.right.top.equalTo(self.view);
|
make.left.right.equalTo(self.view);
|
||||||
|
make.top.equalTo(self.view).offset(16);
|
||||||
make.bottom.equalTo(self.payButton.mas_top).offset(-16);
|
make.bottom.equalTo(self.payButton.mas_top).offset(-16);
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user