2
This commit is contained in:
22
keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/Contents.json
vendored
Normal file
22
keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "pay_leftline_icon@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "pay_leftline_icon@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/pay_leftline_icon@2x.png
vendored
Normal file
BIN
keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/pay_leftline_icon@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 570 B |
BIN
keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/pay_leftline_icon@3x.png
vendored
Normal file
BIN
keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/pay_leftline_icon@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 841 B |
22
keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/Contents.json
vendored
Normal file
22
keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "pay_rightline_icon@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "pay_rightline_icon@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/pay_rightline_icon@2x.png
vendored
Normal file
BIN
keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/pay_rightline_icon@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 580 B |
BIN
keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/pay_rightline_icon@3x.png
vendored
Normal file
BIN
keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/pay_rightline_icon@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 846 B |
@@ -33,11 +33,15 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
@property (nonatomic, copy, nullable) NSString *currency;
|
@property (nonatomic, copy, nullable) NSString *currency;
|
||||||
/// 文案描述
|
/// 文案描述
|
||||||
@property (nonatomic, copy, nullable) NSString *productDescription;
|
@property (nonatomic, copy, nullable) NSString *productDescription;
|
||||||
|
/// 等级:1=VIP, 2=SVIP
|
||||||
|
@property (nonatomic, assign) NSInteger level;
|
||||||
|
|
||||||
/// 展示金币(自动拼接单位)
|
/// 展示金币(自动拼接单位)
|
||||||
- (NSString *)coinsDisplayText;
|
- (NSString *)coinsDisplayText;
|
||||||
/// 展示价格,保留两位小数
|
/// 展示价格,保留两位小数
|
||||||
- (NSString *)priceDisplayText;
|
- (NSString *)priceDisplayText;
|
||||||
|
/// 展示价格数字(不含货币符号)
|
||||||
|
- (NSString *)priceNumberText;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -35,4 +35,8 @@
|
|||||||
return [NSString stringWithFormat:@"%.2f", priceValue];
|
return [NSString stringWithFormat:@"%.2f", priceValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *)priceNumberText {
|
||||||
|
return [NSString stringWithFormat:@"%.2f", self.price];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
|
|
||||||
[self.coverView mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self.coverView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.left.right.equalTo(self.contentView).inset(8);
|
make.left.right.equalTo(self.contentView).inset(16);
|
||||||
make.centerY.equalTo(self.contentView);
|
make.centerY.equalTo(self.contentView);
|
||||||
make.height.mas_equalTo(46);
|
make.height.mas_equalTo(46);
|
||||||
}];
|
}];
|
||||||
|
|||||||
@@ -70,12 +70,15 @@ static NSString * const kKBSvipBenefitBgKind = @"KBSvipBenefitBgDecoration"; //
|
|||||||
UIEdgeInsets sectionInset0 = [self insetForSection:0];
|
UIEdgeInsets sectionInset0 = [self insetForSection:0];
|
||||||
UIEdgeInsets sectionInset1 = [self insetForSection:1];
|
UIEdgeInsets sectionInset1 = [self insetForSection:1];
|
||||||
|
|
||||||
// 1. 外层大背景(18圆角):从 Section 0 顶部到 Section 1 底部
|
// 固定的外层背景边距(不跟随 Section inset)
|
||||||
|
CGFloat outerPadding = 16;
|
||||||
|
|
||||||
|
// 1. 外层大背景(18圆角):固定距离屏幕左右 16
|
||||||
{
|
{
|
||||||
CGFloat minY = CGRectGetMinY(firstItemAttr.frame) - sectionInset0.top;
|
CGFloat minY = CGRectGetMinY(firstItemAttr.frame) - sectionInset0.top;
|
||||||
CGFloat maxY = CGRectGetMaxY(lastBenefitAttr.frame) + 16;
|
CGFloat maxY = CGRectGetMaxY(lastBenefitAttr.frame) + 16;
|
||||||
CGFloat x = sectionInset0.left;
|
CGFloat x = outerPadding;
|
||||||
CGFloat width = self.collectionView.bounds.size.width - sectionInset0.left - sectionInset0.right;
|
CGFloat width = self.collectionView.bounds.size.width - outerPadding * 2;
|
||||||
|
|
||||||
CGRect frame = CGRectMake(x, minY, width, maxY - minY);
|
CGRect frame = CGRectMake(x, minY, width, maxY - minY);
|
||||||
|
|
||||||
@@ -87,10 +90,11 @@ static NSString * const kKBSvipBenefitBgKind = @"KBSvipBenefitBgDecoration"; //
|
|||||||
|
|
||||||
// 2. 内层权益背景(15圆角):从 Section 1 Header 到 Section 1 底部,左右距离外层 8px
|
// 2. 内层权益背景(15圆角):从 Section 1 Header 到 Section 1 底部,左右距离外层 8px
|
||||||
{
|
{
|
||||||
|
CGFloat innerPadding = 8; // 距离外层背景的边距
|
||||||
CGFloat minY = CGRectGetMinY(benefitHeaderAttr.frame);
|
CGFloat minY = CGRectGetMinY(benefitHeaderAttr.frame);
|
||||||
CGFloat maxY = CGRectGetMaxY(lastBenefitAttr.frame) + 16;
|
CGFloat maxY = CGRectGetMaxY(lastBenefitAttr.frame) + 16;
|
||||||
CGFloat x = sectionInset0.left + 8; // 距离外层左边 8px
|
CGFloat x = outerPadding + innerPadding;
|
||||||
CGFloat width = self.collectionView.bounds.size.width - sectionInset0.left - sectionInset0.right - 16; // 左右各 8px
|
CGFloat width = self.collectionView.bounds.size.width - (outerPadding + innerPadding) * 2;
|
||||||
|
|
||||||
CGRect frame = CGRectMake(x, minY, width, maxY - minY);
|
CGRect frame = CGRectMake(x, minY, width, maxY - minY);
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,9 @@
|
|||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@interface KBSvipSubscribeCell : UICollectionViewCell
|
@interface KBSvipSubscribeCell : UICollectionViewCell
|
||||||
/// 配置展示文案
|
/// 配置展示文案(带货币符号)
|
||||||
|
- (void)configTitle:(NSString *)title currency:(NSString *)currency price:(NSString *)price strike:(nullable NSString *)strike;
|
||||||
|
/// 配置展示文案(兼容旧方法)
|
||||||
- (void)configTitle:(NSString *)title price:(NSString *)price strike:(nullable NSString *)strike;
|
- (void)configTitle:(NSString *)title price:(NSString *)price strike:(nullable NSString *)strike;
|
||||||
/// 同步选中态
|
/// 同步选中态
|
||||||
- (void)applySelected:(BOOL)selected animated:(BOOL)animated;
|
- (void)applySelected:(BOOL)selected animated:(BOOL)animated;
|
||||||
|
|||||||
@@ -10,7 +10,9 @@
|
|||||||
@interface KBSvipSubscribeCell ()
|
@interface KBSvipSubscribeCell ()
|
||||||
@property (nonatomic, strong) UIImageView *bgImageView; // 背景图片
|
@property (nonatomic, strong) UIImageView *bgImageView; // 背景图片
|
||||||
@property (nonatomic, strong) UILabel *titleLabel; // "1 Week" / "1 Month" / "1 Year"
|
@property (nonatomic, strong) UILabel *titleLabel; // "1 Week" / "1 Month" / "1 Year"
|
||||||
@property (nonatomic, strong) UILabel *priceLabel; // "$6.90"
|
@property (nonatomic, strong) UIView *priceContainer; // 白色圆角容器
|
||||||
|
@property (nonatomic, strong) UILabel *currencyLabel; // "$" 货币符号
|
||||||
|
@property (nonatomic, strong) UILabel *priceLabel; // "6.90" 价格数字
|
||||||
@property (nonatomic, strong) UILabel *strikeLabel; // 删除线原价
|
@property (nonatomic, strong) UILabel *strikeLabel; // 删除线原价
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -26,19 +28,38 @@
|
|||||||
}];
|
}];
|
||||||
|
|
||||||
[self.contentView addSubview:self.titleLabel];
|
[self.contentView addSubview:self.titleLabel];
|
||||||
[self.contentView addSubview:self.priceLabel];
|
[self.contentView addSubview:self.priceContainer];
|
||||||
[self.contentView addSubview:self.strikeLabel];
|
|
||||||
|
// 价格容器内添加货币符号和价格
|
||||||
|
[self.priceContainer addSubview:self.currencyLabel];
|
||||||
|
[self.priceContainer addSubview:self.priceLabel];
|
||||||
|
[self.priceContainer addSubview:self.strikeLabel];
|
||||||
|
|
||||||
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.centerX.equalTo(self.contentView);
|
make.centerX.equalTo(self.contentView);
|
||||||
make.top.equalTo(self.contentView).offset(12);
|
make.top.equalTo(self.contentView).offset(10);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
[self.priceContainer mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.left.equalTo(self.contentView).offset(5);
|
||||||
|
make.right.equalTo(self.contentView).offset(-5);
|
||||||
|
make.bottom.equalTo(self.contentView).offset(-5);
|
||||||
|
make.height.mas_equalTo(86);
|
||||||
|
}];
|
||||||
|
|
||||||
|
// 货币符号和价格水平居中
|
||||||
|
[self.currencyLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.right.equalTo(self.priceLabel.mas_left).offset(-2);
|
||||||
|
make.bottom.equalTo(self.priceLabel.mas_bottom).offset(-4); // 底部对齐,稍微上移
|
||||||
|
}];
|
||||||
|
|
||||||
[self.priceLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self.priceLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.centerX.equalTo(self.contentView);
|
make.centerX.equalTo(self.priceContainer).offset(6); // 稍微右移,给货币符号留空间
|
||||||
make.top.equalTo(self.titleLabel.mas_bottom).offset(8);
|
make.centerY.equalTo(self.priceContainer).offset(-8);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[self.strikeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self.strikeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.centerX.equalTo(self.contentView);
|
make.centerX.equalTo(self.priceContainer);
|
||||||
make.top.equalTo(self.priceLabel.mas_bottom).offset(4);
|
make.top.equalTo(self.priceLabel.mas_bottom).offset(4);
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
@@ -55,9 +76,10 @@
|
|||||||
[self applySelected:selected animated:NO];
|
[self applySelected:selected animated:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)configTitle:(NSString *)title price:(NSString *)price strike:(nullable NSString *)strike {
|
- (void)configTitle:(NSString *)title currency:(NSString *)currency price:(NSString *)price strike:(nullable NSString *)strike {
|
||||||
self.titleLabel.text = title.length ? title : @"1 Month";
|
self.titleLabel.text = title.length ? title : @"1 Month";
|
||||||
self.priceLabel.text = price.length ? price : @"$6.90";
|
self.currencyLabel.text = currency.length ? currency : @"$";
|
||||||
|
self.priceLabel.text = price.length ? price : @"6.90";
|
||||||
self.strikeLabel.hidden = (strike.length == 0);
|
self.strikeLabel.hidden = (strike.length == 0);
|
||||||
if (strike.length) {
|
if (strike.length) {
|
||||||
NSDictionary *attr = @{
|
NSDictionary *attr = @{
|
||||||
@@ -68,6 +90,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 兼容旧方法
|
||||||
|
- (void)configTitle:(NSString *)title price:(NSString *)price strike:(nullable NSString *)strike {
|
||||||
|
[self configTitle:title currency:@"$" price:price strike:strike];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)applySelected:(BOOL)selected animated:(BOOL)animated {
|
- (void)applySelected:(BOOL)selected animated:(BOOL)animated {
|
||||||
NSString *imageName = selected ? @"pay_colorbg_icon" : @"pay_graybg_icon";
|
NSString *imageName = selected ? @"pay_colorbg_icon" : @"pay_graybg_icon";
|
||||||
void (^changes)(void) = ^{
|
void (^changes)(void) = ^{
|
||||||
@@ -101,12 +128,32 @@
|
|||||||
return _titleLabel;
|
return _titleLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (UIView *)priceContainer {
|
||||||
|
if (!_priceContainer) {
|
||||||
|
_priceContainer = [UIView new];
|
||||||
|
_priceContainer.backgroundColor = [UIColor whiteColor];
|
||||||
|
_priceContainer.layer.cornerRadius = 14;
|
||||||
|
_priceContainer.clipsToBounds = YES;
|
||||||
|
}
|
||||||
|
return _priceContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UILabel *)currencyLabel {
|
||||||
|
if (!_currencyLabel) {
|
||||||
|
_currencyLabel = [UILabel new];
|
||||||
|
_currencyLabel.text = @"$";
|
||||||
|
_currencyLabel.textColor = [UIColor colorWithHex:KBBlackValue];
|
||||||
|
_currencyLabel.font = [KBFont medium:14]; // 货币符号字体较小
|
||||||
|
}
|
||||||
|
return _currencyLabel;
|
||||||
|
}
|
||||||
|
|
||||||
- (UILabel *)priceLabel {
|
- (UILabel *)priceLabel {
|
||||||
if (!_priceLabel) {
|
if (!_priceLabel) {
|
||||||
_priceLabel = [UILabel new];
|
_priceLabel = [UILabel new];
|
||||||
_priceLabel.text = @"$6.90";
|
_priceLabel.text = @"6.90";
|
||||||
_priceLabel.textColor = [UIColor colorWithHex:KBBlackValue];
|
_priceLabel.textColor = [UIColor colorWithHex:KBBlackValue];
|
||||||
_priceLabel.font = [KBFont bold:22];
|
_priceLabel.font = [KBFont bold:22]; // 价格数字字体较大
|
||||||
}
|
}
|
||||||
return _priceLabel;
|
return _priceLabel;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,8 +118,15 @@ static NSString * const kKBSvipBenefitHeaderId = @"kKBSvipBenefitHeaderId";
|
|||||||
[self.collectionView reloadData];
|
[self.collectionView reloadData];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.plans = products ?: @[];
|
// 过滤 level=2 的 SVIP 数据
|
||||||
self.selectedIndex = self.plans.count > 0 ? 1 : NSNotFound; // 默认选中第二个(1 Month)
|
NSMutableArray<KBPayProductModel *> *svipProducts = [NSMutableArray array];
|
||||||
|
for (KBPayProductModel *product in products) {
|
||||||
|
if (product.level == 1) {
|
||||||
|
[svipProducts addObject:product];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.plans = svipProducts.copy;
|
||||||
|
self.selectedIndex = self.plans.count > 1 ? 1 : (self.plans.count > 0 ? 0 : NSNotFound); // 默认选中第二个(1 Month)
|
||||||
[self.collectionView reloadData];
|
[self.collectionView reloadData];
|
||||||
[self selectCurrentPlanAnimated:NO];
|
[self selectCurrentPlanAnimated:NO];
|
||||||
[self prepareStoreKitWithPlans:self.plans];
|
[self prepareStoreKitWithPlans:self.plans];
|
||||||
@@ -231,8 +238,9 @@ static NSString * const kKBSvipBenefitHeaderId = @"kKBSvipBenefitHeaderId";
|
|||||||
if (indexPath.item < self.plans.count) {
|
if (indexPath.item < self.plans.count) {
|
||||||
KBPayProductModel *plan = self.plans[indexPath.item];
|
KBPayProductModel *plan = self.plans[indexPath.item];
|
||||||
NSString *title = [self displayTitleForPlan:plan];
|
NSString *title = [self displayTitleForPlan:plan];
|
||||||
NSString *price = [plan priceDisplayText];
|
NSString *currency = plan.currency ?: @"$";
|
||||||
[cell configTitle:title price:price strike:nil];
|
NSString *price = [plan priceNumberText];
|
||||||
|
[cell configTitle:title currency:currency price:price strike:nil];
|
||||||
[cell applySelected:(indexPath.item == self.selectedIndex) animated:NO];
|
[cell applySelected:(indexPath.item == self.selectedIndex) animated:NO];
|
||||||
}
|
}
|
||||||
return cell;
|
return cell;
|
||||||
@@ -264,22 +272,22 @@ static NSString * const kKBSvipBenefitHeaderId = @"kKBSvipBenefitHeaderId";
|
|||||||
make.center.equalTo(header);
|
make.center.equalTo(header);
|
||||||
}];
|
}];
|
||||||
// 左右横线
|
// 左右横线
|
||||||
UIView *leftLine = [UIView new];
|
UIImageView *leftLine = [UIImageView new];
|
||||||
leftLine.backgroundColor = [UIColor colorWithHex:0xE5E5E5];
|
leftLine.image = [UIImage imageNamed:@"pay_leftline_icon"];
|
||||||
[header addSubview:leftLine];
|
[header addSubview:leftLine];
|
||||||
[leftLine mas_makeConstraints:^(MASConstraintMaker *make) {
|
[leftLine mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.right.equalTo(titleLabel.mas_left).offset(-12);
|
make.right.equalTo(titleLabel.mas_left).offset(-12);
|
||||||
make.centerY.equalTo(header);
|
make.centerY.equalTo(header);
|
||||||
make.width.mas_equalTo(40);
|
make.width.mas_equalTo(53);
|
||||||
make.height.mas_equalTo(1);
|
make.height.mas_equalTo(1);
|
||||||
}];
|
}];
|
||||||
UIView *rightLine = [UIView new];
|
UIImageView *rightLine = [UIImageView new];
|
||||||
rightLine.backgroundColor = [UIColor colorWithHex:0xE5E5E5];
|
rightLine.image = [UIImage imageNamed:@"pay_rightline_icon"];
|
||||||
[header addSubview:rightLine];
|
[header addSubview:rightLine];
|
||||||
[rightLine mas_makeConstraints:^(MASConstraintMaker *make) {
|
[rightLine mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.left.equalTo(titleLabel.mas_right).offset(12);
|
make.left.equalTo(titleLabel.mas_right).offset(12);
|
||||||
make.centerY.equalTo(header);
|
make.centerY.equalTo(header);
|
||||||
make.width.mas_equalTo(40);
|
make.width.mas_equalTo(53);
|
||||||
make.height.mas_equalTo(1);
|
make.height.mas_equalTo(1);
|
||||||
}];
|
}];
|
||||||
return header;
|
return header;
|
||||||
@@ -361,7 +369,8 @@ static NSString * const kKBSvipBenefitHeaderId = @"kKBSvipBenefitHeaderId";
|
|||||||
|
|
||||||
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
|
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
|
||||||
if (section == 0) {
|
if (section == 0) {
|
||||||
return UIEdgeInsetsMake(16, 16, 10, 16);
|
// 订阅选项:外层背景距屏幕16,Cell距外层背景17,所以 16+17=33
|
||||||
|
return UIEdgeInsetsMake(16, 22, 10, 22);
|
||||||
}
|
}
|
||||||
return UIEdgeInsetsMake(0, 16, 20, 16);
|
return UIEdgeInsetsMake(0, 16, 20, 16);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user