添加pay

This commit is contained in:
2025-11-13 21:22:10 +08:00
parent ae79d1b1ba
commit d164514fcf
12 changed files with 709 additions and 56 deletions

View File

@@ -0,0 +1,21 @@
//
// KBJfPayCell.h
// 积分充值选项 Cell自定义样式
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface KBJfPayCell : UICollectionViewCell
/// 配置展示:金币数量 + 价格
- (void)configCoins:(NSString *)coins price:(NSString *)price;
/// 刷新选中态(带动画可选)
- (void)applySelected:(BOOL)selected animated:(BOOL)animated;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,232 @@
//
// KBJfPayCell.m
// Cell
// - +
// -
// - 绿 +
//
#import "KBJfPayCell.h"
// CAShapeLayer +
@interface KBPayCheckBadgeView : UIView
@property (nonatomic, assign) BOOL checked;
@end
@implementation KBPayCheckBadgeView {
CAShapeLayer *_circle;
CAShapeLayer *_check;
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = UIColor.clearColor;
_circle = [CAShapeLayer layer];
_circle.fillColor = [UIColor colorWithHex:KBColorValue].CGColor; // 绿
[self.layer addSublayer:_circle];
_check = [CAShapeLayer layer];
_check.strokeColor = UIColor.whiteColor.CGColor;
_check.fillColor = UIColor.clearColor.CGColor;
_check.lineWidth = 2.0;
_check.lineCap = kCALineCapRound;
_check.lineJoin = kCALineJoinRound;
[self.layer addSublayer:_check];
self.hidden = YES;
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGFloat s = MIN(self.bounds.size.width, self.bounds.size.height);
CGRect r = CGRectMake((self.bounds.size.width - s) * 0.5, (self.bounds.size.height - s) * 0.5, s, s);
UIBezierPath *circle = [UIBezierPath bezierPathWithOvalInRect:r];
_circle.path = circle.CGPath;
//
CGPoint p1 = CGPointMake(CGRectGetMinX(r) + s*0.26, CGRectGetMinY(r) + s*0.55);
CGPoint p2 = CGPointMake(CGRectGetMinX(r) + s*0.45, CGRectGetMinY(r) + s*0.74);
CGPoint p3 = CGPointMake(CGRectGetMinX(r) + s*0.76, CGRectGetMinY(r) + s*0.26);
UIBezierPath *check = [UIBezierPath bezierPath];
[check moveToPoint:p1];
[check addLineToPoint:p2];
[check addLineToPoint:p3];
_check.path = check.CGPath;
}
@end
@interface KBJfPayCell ()
@property (nonatomic, strong) UIView *cardView; //
@property (nonatomic, strong) UIStackView *topStack; // +
@property (nonatomic, strong) UIImageView *iconView; //
@property (nonatomic, strong) UILabel *coinLabel; // 690
@property (nonatomic, strong) UILabel *priceLabel; // $6.90
@property (nonatomic, strong) KBPayCheckBadgeView *badge; //
@property (nonatomic, strong) CAShapeLayer *borderLayer; //
@property (nonatomic, strong) CAShapeLayer *shadowLayer; //
@end
@implementation KBJfPayCell
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.contentView.backgroundColor = UIColor.clearColor;
[self.contentView addSubview:self.cardView];
// +
[self.cardView addSubview:self.topStack];
[self.topStack addArrangedSubview:self.iconView];
[self.topStack addArrangedSubview:self.coinLabel];
[self.cardView addSubview:self.priceLabel];
[self.contentView addSubview:self.badge];
[self.cardView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.contentView);
}];
[self.topStack mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.cardView).offset(16);
make.centerX.equalTo(self.cardView); //
}];
[self.iconView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(18);
}];
[self.priceLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.cardView);
make.top.equalTo(self.topStack.mas_bottom).offset(8);
}];
[self.badge mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.cardView);
make.bottom.equalTo(self.cardView).offset(12); //
make.width.height.mas_equalTo(20);
}];
//
self.borderLayer = [CAShapeLayer layer];
self.borderLayer.strokeColor = [UIColor colorWithHex:KBColorValue].CGColor;
self.borderLayer.fillColor = UIColor.clearColor.CGColor;
self.borderLayer.lineWidth = 2.0;
self.borderLayer.hidden = YES;
[self.cardView.layer addSublayer:self.borderLayer];
// 绿
self.shadowLayer = [CAShapeLayer layer];
self.shadowLayer.fillColor = UIColor.clearColor.CGColor; //
self.shadowLayer.strokeColor = UIColor.clearColor.CGColor;
self.shadowLayer.shadowColor = [UIColor colorWithHex:KBColorValue].CGColor; // 0x02BEAC
self.shadowLayer.shadowOpacity = 0.45; //
self.shadowLayer.shadowOffset = CGSizeMake(0, 6); //
self.shadowLayer.shadowRadius = 8.0; //
self.shadowLayer.hidden = YES;
// contentView
[self.contentView.layer insertSublayer:self.shadowLayer atIndex:0];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGFloat radius = 18;
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.cardView.bounds cornerRadius:radius];
self.cardView.layer.cornerRadius = radius;
self.cardView.layer.masksToBounds = YES; // shadowLayer
self.borderLayer.path = path.CGPath;
self.borderLayer.frame = self.cardView.bounds;
// contentView
CGRect cardRectInContent = self.cardView.frame;
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRoundedRect:cardRectInContent cornerRadius:radius];
self.shadowLayer.frame = self.contentView.bounds;
self.shadowLayer.shadowPath = shadowPath.CGPath;
}
- (void)prepareForReuse {
[super prepareForReuse];
[self applySelected:NO animated:NO];
}
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
// UI selectItemAtIndexPath /
[self applySelected:selected animated:NO];
}
- (void)configCoins:(NSString *)coins price:(NSString *)price {
self.coinLabel.text = coins.length ? coins : @"690";
self.priceLabel.text = price.length ? price : @"$6.90";
}
- (void)applySelected:(BOOL)selected animated:(BOOL)animated {
self.borderLayer.hidden = !selected;
self.badge.hidden = !selected;
self.shadowLayer.hidden = !selected; //
void (^animations)(void) = ^{
self.cardView.layer.shadowOpacity = selected ? 0.0 : 0.0; //
};
if (animated) {
[UIView animateWithDuration:0.15 animations:animations];
} else {
animations();
}
}
#pragma mark - Lazy UI
- (UIView *)cardView {
if (!_cardView) {
_cardView = [UIView new];
// /
_cardView.backgroundColor = [UIColor colorWithWhite:0.98 alpha:1.0];
}
return _cardView;
}
- (UIImageView *)iconView {
if (!_iconView) {
_iconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"shop_jb_icon"]];
_iconView.contentMode = UIViewContentModeScaleAspectFit;
}
return _iconView;
}
- (UILabel *)coinLabel {
if (!_coinLabel) {
_coinLabel = [UILabel new];
_coinLabel.text = @"690";
_coinLabel.font = [UIFont systemFontOfSize:20 weight:UIFontWeightBold];
_coinLabel.textColor = [UIColor colorWithHex:KBBlackValue];
}
return _coinLabel;
}
- (UILabel *)priceLabel {
if (!_priceLabel) {
_priceLabel = [UILabel new];
_priceLabel.text = @"$6.90";
_priceLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightSemibold];
_priceLabel.textColor = [UIColor colorWithHex:KBColorValue];
}
return _priceLabel;
}
- (KBPayCheckBadgeView *)badge {
if (!_badge) {
_badge = [[KBPayCheckBadgeView alloc] initWithFrame:CGRectZero];
_badge.userInteractionEnabled = NO;
}
return _badge;
}
- (UIStackView *)topStack {
if (!_topStack) {
_topStack = [[UIStackView alloc] initWithArrangedSubviews:@[]];
_topStack.axis = UILayoutConstraintAxisHorizontal; //
_topStack.alignment = UIStackViewAlignmentCenter;
_topStack.spacing = 6;
_topStack.distribution = UIStackViewDistributionFill;
}
return _topStack;
}
@end