187 lines
6.2 KiB
Objective-C
187 lines
6.2 KiB
Objective-C
//
|
||
// 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:KBColorValue] : [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.mas_equalTo(KBFit(126));
|
||
}];
|
||
[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
|