处理svip
This commit is contained in:
16
keyBoard/Class/Pay/V/KBSvipBenefitBgView.h
Normal file
16
keyBoard/Class/Pay/V/KBSvipBenefitBgView.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// KBSvipBenefitBgView.h
|
||||
// keyBoard
|
||||
//
|
||||
// 权益列表背景装饰视图
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface KBSvipBenefitBgView : UICollectionReusableView
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
21
keyBoard/Class/Pay/V/KBSvipBenefitBgView.m
Normal file
21
keyBoard/Class/Pay/V/KBSvipBenefitBgView.m
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// KBSvipBenefitBgView.m
|
||||
// keyBoard
|
||||
//
|
||||
// 权益列表背景装饰视图:白色背景 + 15圆角
|
||||
//
|
||||
|
||||
#import "KBSvipBenefitBgView.h"
|
||||
|
||||
@implementation KBSvipBenefitBgView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
self.backgroundColor = [UIColor whiteColor];
|
||||
self.layer.cornerRadius = 15;
|
||||
self.layer.masksToBounds = YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
17
keyBoard/Class/Pay/V/KBSvipBenefitCell.h
Normal file
17
keyBoard/Class/Pay/V/KBSvipBenefitCell.h
Normal file
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// KBSvipBenefitCell.h
|
||||
// keyBoard
|
||||
//
|
||||
// SVIP 权益项 Cell:左侧图标 + 文字 + 右侧勾选
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface KBSvipBenefitCell : UICollectionViewCell
|
||||
/// 配置权益项
|
||||
- (void)configWithIcon:(NSString *)iconName title:(NSString *)title;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
88
keyBoard/Class/Pay/V/KBSvipBenefitCell.m
Normal file
88
keyBoard/Class/Pay/V/KBSvipBenefitCell.m
Normal file
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// KBSvipBenefitCell.m
|
||||
// keyBoard
|
||||
//
|
||||
// SVIP 权益项样式:左侧图标 + 文字 + 右侧勾选
|
||||
//
|
||||
|
||||
#import "KBSvipBenefitCell.h"
|
||||
|
||||
@interface KBSvipBenefitCell ()
|
||||
@property (nonatomic, strong) UIImageView *iconView; // 左侧图标
|
||||
@property (nonatomic, strong) UILabel *titleLabel; // 权益文字
|
||||
@property (nonatomic, strong) UIImageView *checkView; // 右侧勾选
|
||||
@end
|
||||
|
||||
@implementation KBSvipBenefitCell
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
self.contentView.backgroundColor = [UIColor clearColor];
|
||||
|
||||
[self.contentView addSubview:self.iconView];
|
||||
[self.contentView addSubview:self.titleLabel];
|
||||
[self.contentView addSubview:self.checkView];
|
||||
|
||||
[self.iconView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.contentView).offset(16);
|
||||
make.centerY.equalTo(self.contentView);
|
||||
make.width.height.mas_equalTo(40);
|
||||
}];
|
||||
|
||||
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.iconView.mas_right).offset(12);
|
||||
make.centerY.equalTo(self.contentView);
|
||||
make.right.lessThanOrEqualTo(self.checkView.mas_left).offset(-12);
|
||||
}];
|
||||
|
||||
[self.checkView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.right.equalTo(self.contentView).offset(-16);
|
||||
make.centerY.equalTo(self.contentView);
|
||||
make.width.height.mas_equalTo(20);
|
||||
}];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)configWithIcon:(NSString *)iconName title:(NSString *)title {
|
||||
if (iconName.length) {
|
||||
self.iconView.image = [UIImage imageNamed:iconName];
|
||||
}
|
||||
self.titleLabel.text = title.length ? title : @"";
|
||||
}
|
||||
|
||||
#pragma mark - Lazy
|
||||
- (UIImageView *)iconView {
|
||||
if (!_iconView) {
|
||||
_iconView = [UIImageView new];
|
||||
_iconView.contentMode = UIViewContentModeScaleAspectFit;
|
||||
_iconView.layer.cornerRadius = 8;
|
||||
_iconView.clipsToBounds = YES;
|
||||
}
|
||||
return _iconView;
|
||||
}
|
||||
|
||||
- (UILabel *)titleLabel {
|
||||
if (!_titleLabel) {
|
||||
_titleLabel = [UILabel new];
|
||||
_titleLabel.textColor = [UIColor colorWithHex:KBBlackValue];
|
||||
_titleLabel.font = [KBFont regular:14];
|
||||
}
|
||||
return _titleLabel;
|
||||
}
|
||||
|
||||
- (UIImageView *)checkView {
|
||||
if (!_checkView) {
|
||||
_checkView = [UIImageView new];
|
||||
_checkView.contentMode = UIViewContentModeScaleAspectFit;
|
||||
// 使用 SF Symbol 勾选图标
|
||||
if (@available(iOS 13.0, *)) {
|
||||
UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithWeight:UIImageSymbolWeightMedium];
|
||||
_checkView.image = [UIImage systemImageNamed:@"checkmark" withConfiguration:config];
|
||||
}
|
||||
_checkView.tintColor = [UIColor colorWithHex:KBColorValue];
|
||||
}
|
||||
return _checkView;
|
||||
}
|
||||
|
||||
@end
|
||||
19
keyBoard/Class/Pay/V/KBSvipFlowLayout.h
Normal file
19
keyBoard/Class/Pay/V/KBSvipFlowLayout.h
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// KBSvipFlowLayout.h
|
||||
// keyBoard
|
||||
//
|
||||
// SVIP 页面自定义布局,支持 Section 背景装饰视图
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface KBSvipFlowLayout : UICollectionViewFlowLayout
|
||||
|
||||
/// 需要添加背景的 Section 索引(默认 Section 1)
|
||||
@property (nonatomic, assign) NSInteger decorationSection;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
90
keyBoard/Class/Pay/V/KBSvipFlowLayout.m
Normal file
90
keyBoard/Class/Pay/V/KBSvipFlowLayout.m
Normal file
@@ -0,0 +1,90 @@
|
||||
//
|
||||
// KBSvipFlowLayout.m
|
||||
// keyBoard
|
||||
//
|
||||
// SVIP 页面自定义布局,支持 Section 背景装饰视图
|
||||
//
|
||||
|
||||
#import "KBSvipFlowLayout.h"
|
||||
#import "KBSvipBenefitBgView.h"
|
||||
|
||||
static NSString * const kKBSvipDecorationViewKind = @"KBSvipBenefitBgDecoration";
|
||||
|
||||
@interface KBSvipFlowLayout ()
|
||||
@property (nonatomic, strong) NSMutableArray<UICollectionViewLayoutAttributes *> *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<UICollectionViewDelegateFlowLayout>)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
|
||||
19
keyBoard/Class/Pay/V/KBSvipSubscribeCell.h
Normal file
19
keyBoard/Class/Pay/V/KBSvipSubscribeCell.h
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// KBSvipSubscribeCell.h
|
||||
// keyBoard
|
||||
//
|
||||
// SVIP 订阅选项 Cell:横向排列,选中时绿色边框
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface KBSvipSubscribeCell : UICollectionViewCell
|
||||
/// 配置展示文案
|
||||
- (void)configTitle:(NSString *)title price:(NSString *)price strike:(nullable NSString *)strike;
|
||||
/// 同步选中态
|
||||
- (void)applySelected:(BOOL)selected animated:(BOOL)animated;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
130
keyBoard/Class/Pay/V/KBSvipSubscribeCell.m
Normal file
130
keyBoard/Class/Pay/V/KBSvipSubscribeCell.m
Normal file
@@ -0,0 +1,130 @@
|
||||
//
|
||||
// KBSvipSubscribeCell.m
|
||||
// keyBoard
|
||||
//
|
||||
// SVIP 订阅选项样式,横向排列,选中时绿色边框
|
||||
//
|
||||
|
||||
#import "KBSvipSubscribeCell.h"
|
||||
|
||||
@interface KBSvipSubscribeCell ()
|
||||
@property (nonatomic, strong) UIView *cardView; // 白色卡片背景
|
||||
@property (nonatomic, strong) UILabel *titleLabel; // "1 Week" / "1 Month" / "1 Year"
|
||||
@property (nonatomic, strong) UILabel *priceLabel; // "$6.90"
|
||||
@property (nonatomic, strong) UILabel *strikeLabel; // 删除线原价
|
||||
@end
|
||||
|
||||
@implementation KBSvipSubscribeCell
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
self.contentView.backgroundColor = [UIColor clearColor];
|
||||
|
||||
[self.contentView addSubview:self.cardView];
|
||||
[self.cardView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.equalTo(self.contentView);
|
||||
}];
|
||||
|
||||
[self.cardView addSubview:self.titleLabel];
|
||||
[self.cardView addSubview:self.priceLabel];
|
||||
[self.cardView addSubview:self.strikeLabel];
|
||||
|
||||
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerX.equalTo(self.cardView);
|
||||
make.top.equalTo(self.cardView).offset(12);
|
||||
}];
|
||||
[self.priceLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerX.equalTo(self.cardView);
|
||||
make.top.equalTo(self.titleLabel.mas_bottom).offset(8);
|
||||
}];
|
||||
[self.strikeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerX.equalTo(self.cardView);
|
||||
make.top.equalTo(self.priceLabel.mas_bottom).offset(4);
|
||||
}];
|
||||
|
||||
// 基于 CALayer 的边框
|
||||
self.cardView.layer.borderWidth = 1.5;
|
||||
self.cardView.layer.borderColor = [UIColor colorWithWhite:0.9 alpha:1.0].CGColor;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)prepareForReuse {
|
||||
[super prepareForReuse];
|
||||
[self applySelected:NO animated:NO];
|
||||
}
|
||||
|
||||
- (void)setSelected:(BOOL)selected {
|
||||
[super setSelected:selected];
|
||||
[self applySelected:selected animated:NO];
|
||||
}
|
||||
|
||||
- (void)configTitle:(NSString *)title price:(NSString *)price strike:(nullable NSString *)strike {
|
||||
self.titleLabel.text = title.length ? title : @"1 Month";
|
||||
self.priceLabel.text = price.length ? price : @"$6.90";
|
||||
self.strikeLabel.hidden = (strike.length == 0);
|
||||
if (strike.length) {
|
||||
NSDictionary *attr = @{
|
||||
NSStrikethroughStyleAttributeName: @(NSUnderlineStyleSingle),
|
||||
NSForegroundColorAttributeName: [UIColor colorWithHex:0x999999]
|
||||
};
|
||||
self.strikeLabel.attributedText = [[NSAttributedString alloc] initWithString:strike attributes:attr];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)applySelected:(BOOL)selected animated:(BOOL)animated {
|
||||
CGColorRef color = (selected ? [UIColor colorWithHex:KBColorValue].CGColor : [UIColor colorWithWhite:0.9 alpha:1.0].CGColor);
|
||||
UIColor *bgColor = selected ? [UIColor colorWithHex:0xE8FFF6] : [UIColor whiteColor];
|
||||
void (^changes)(void) = ^{
|
||||
self.cardView.layer.borderColor = color;
|
||||
self.cardView.backgroundColor = bgColor;
|
||||
};
|
||||
if (animated) {
|
||||
[UIView animateWithDuration:0.2 animations:changes];
|
||||
} else {
|
||||
changes();
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Lazy
|
||||
- (UIView *)cardView {
|
||||
if (!_cardView) {
|
||||
_cardView = [UIView new];
|
||||
_cardView.backgroundColor = [UIColor whiteColor];
|
||||
_cardView.layer.cornerRadius = 12;
|
||||
_cardView.clipsToBounds = YES;
|
||||
}
|
||||
return _cardView;
|
||||
}
|
||||
|
||||
- (UILabel *)titleLabel {
|
||||
if (!_titleLabel) {
|
||||
_titleLabel = [UILabel new];
|
||||
_titleLabel.text = @"1 Month";
|
||||
_titleLabel.textColor = [UIColor colorWithHex:KBBlackValue];
|
||||
_titleLabel.font = [KBFont medium:13];
|
||||
}
|
||||
return _titleLabel;
|
||||
}
|
||||
|
||||
- (UILabel *)priceLabel {
|
||||
if (!_priceLabel) {
|
||||
_priceLabel = [UILabel new];
|
||||
_priceLabel.text = @"$6.90";
|
||||
_priceLabel.textColor = [UIColor colorWithHex:KBBlackValue];
|
||||
_priceLabel.font = [KBFont bold:22];
|
||||
}
|
||||
return _priceLabel;
|
||||
}
|
||||
|
||||
- (UILabel *)strikeLabel {
|
||||
if (!_strikeLabel) {
|
||||
_strikeLabel = [UILabel new];
|
||||
_strikeLabel.text = @"$4.49";
|
||||
_strikeLabel.font = [KBFont regular:12];
|
||||
_strikeLabel.textColor = [UIColor colorWithHex:0x999999];
|
||||
}
|
||||
return _strikeLabel;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user