This commit is contained in:
2025-11-08 21:44:41 +08:00
parent a729396401
commit 41b14ceea4
6 changed files with 498 additions and 1 deletions

View File

@@ -0,0 +1,25 @@
//
// MySkinCell.h
// keyBoard
//
// 我的皮肤 - 列表 cell。编辑态显示选择圆点。
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface MySkinCell : UICollectionViewCell
/// 是否处于编辑态(显示左上角选择圆点)
@property (nonatomic, assign, getter=isEditing) BOOL editing;
/// 配置显示内容(演示仅传标题与占位图)
- (void)configWithTitle:(NSString *)title image:(nullable UIImage *)image;
/// 根据选中状态刷新打勾样式(供外部在 select/deselect 时调用)
- (void)updateSelected:(BOOL)selected;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,186 @@
//
// MySkinCell.m
// keyBoard
//
#import "MySkinCell.h"
#import <Masonry/Masonry.h>
#import "UIColor+Extension.h"
// + CAShapeLayer
@interface KBSelectDotView : UIView
@property (nonatomic, assign) BOOL selectedState; //
- (void)applySelected:(BOOL)selected; //
@end
@implementation KBSelectDotView {
CAShapeLayer *_circleLayer; //
CAShapeLayer *_checkLayer; //
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = UIColor.clearColor;
_circleLayer = [CAShapeLayer layer];
_circleLayer.fillColor = [UIColor colorWithWhite:0 alpha:0.51].CGColor; // #000000 51%
[self.layer addSublayer:_circleLayer];
_checkLayer = [CAShapeLayer layer];
_checkLayer.strokeColor = UIColor.whiteColor.CGColor; //
_checkLayer.fillColor = UIColor.clearColor.CGColor;
_checkLayer.lineWidth = 2.0;
_checkLayer.lineCap = kCALineCapRound;
_checkLayer.lineJoin = kCALineJoinRound;
_checkLayer.hidden = YES; //
[self.layer addSublayer:_checkLayer];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGFloat size = MIN(self.bounds.size.width, self.bounds.size.height);
CGRect r = CGRectMake((self.bounds.size.width - size) * 0.5,
(self.bounds.size.height - size) * 0.5,
size, size);
UIBezierPath *circle = [UIBezierPath bezierPathWithOvalInRect:r];
_circleLayer.path = circle.CGPath;
// size
CGFloat s = size;
CGPoint p1 = CGPointMake(CGRectGetMinX(r) + s * 0.26, CGRectGetMinY(r) + s * 0.55);
CGPoint p2 = CGPointMake(CGRectGetMinX(r) + s * 0.43, CGRectGetMinY(r) + s * 0.72);
CGPoint p3 = CGPointMake(CGRectGetMinX(r) + s * 0.76, CGRectGetMinY(r) + s * 0.28);
UIBezierPath *check = [UIBezierPath bezierPath];
[check moveToPoint:p1];
[check addLineToPoint:p2];
[check addLineToPoint:p3];
_checkLayer.path = check.CGPath;
}
- (void)applySelected:(BOOL)selected {
self.selectedState = selected;
UIColor *fill = selected ? [UIColor colorWithHex:0x02BEAC] : [UIColor colorWithWhite:0 alpha:0.51];
_circleLayer.fillColor = fill.CGColor; // #02BEAC
_checkLayer.hidden = !selected; //
}
@end
@interface MySkinCell ()
@property (nonatomic, strong) UIView *cardView; //
@property (nonatomic, strong) UIImageView *coverView; //
@property (nonatomic, strong) UILabel *titleLabel; //
@property (nonatomic, strong) KBSelectDotView *markView; //
@end
@implementation MySkinCell
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.contentView.backgroundColor = [UIColor whiteColor];
[self.contentView addSubview:self.cardView];
[self.cardView addSubview:self.coverView];
[self.cardView addSubview:self.titleLabel];
[self.contentView addSubview:self.markView];
[self.cardView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.contentView);
}];
[self.coverView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.right.equalTo(self.cardView);
make.height.equalTo(self.cardView.mas_width).multipliedBy(0.66); //
}];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.cardView).offset(12);
make.right.equalTo(self.cardView).offset(-12);
make.top.equalTo(self.coverView.mas_bottom).offset(10);
}];
[self.markView mas_makeConstraints:^(MASConstraintMaker *make) {
// contentView cardView/masksToBounds
make.left.equalTo(self.contentView).offset(8);
make.top.equalTo(self.contentView).offset(8);
make.width.height.mas_equalTo(15); // 15px
}];
self.markView.hidden = YES; //
}
return self;
}
- (void)prepareForReuse {
[super prepareForReuse];
self.editing = NO;
[self updateSelected:NO];
}
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
//
[self updateSelected:selected];
}
- (void)configWithTitle:(NSString *)title image:(UIImage *)image {
self.titleLabel.text = title.length ? title : @"Dopamine";
//
self.coverView.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1.0];
}
- (void)setEditing:(BOOL)editing {
_editing = editing;
self.markView.hidden = !editing;
if (editing) { [self.markView applySelected:self.isSelected]; }
}
- (void)updateSelected:(BOOL)selected {
if (!self.isEditing) {
self.markView.hidden = YES;
return;
}
self.markView.hidden = NO;
[self.markView applySelected:selected];
}
#pragma mark - Lazy
- (UIView *)cardView {
if (!_cardView) {
_cardView = [UIView new];
_cardView.backgroundColor = [UIColor colorWithWhite:0.97 alpha:1.0];
_cardView.layer.cornerRadius = 12;
_cardView.layer.masksToBounds = YES;
}
return _cardView;
}
- (UIImageView *)coverView {
if (!_coverView) {
_coverView = [[UIImageView alloc] init];
_coverView.contentMode = UIViewContentModeScaleAspectFill;
_coverView.clipsToBounds = YES;
}
return _coverView;
}
- (UILabel *)titleLabel {
if (!_titleLabel) {
_titleLabel = [UILabel new];
_titleLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightSemibold];
_titleLabel.textColor = [UIColor colorWithHex:0x333333];
_titleLabel.text = @"Dopamine";
}
return _titleLabel;
}
- (KBSelectDotView *)markView {
if (!_markView) {
_markView = [[KBSelectDotView alloc] init];
_markView.userInteractionEnabled = NO; //
_markView.layer.zPosition = 10; //
}
return _markView;
}
@end