3
This commit is contained in:
@@ -61,6 +61,8 @@
|
||||
048908D22EBF611D00FABA60 /* KBHistoryMoreCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908D12EBF611D00FABA60 /* KBHistoryMoreCell.m */; };
|
||||
048908DA2EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908D82EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout.m */; };
|
||||
048908DD2EBF67EB00FABA60 /* KBSearchResultVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908DC2EBF67EB00FABA60 /* KBSearchResultVC.m */; };
|
||||
048908E02EBF73DC00FABA60 /* MySkinVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908DF2EBF73DC00FABA60 /* MySkinVC.m */; };
|
||||
048908E32EBF760000FABA60 /* MySkinCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908E22EBF760000FABA60 /* MySkinCell.m */; };
|
||||
04A9FE0F2EB481100020DB6D /* KBHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97082EB31B14007BD342 /* KBHUD.m */; };
|
||||
04A9FE132EB4D0D20020DB6D /* KBFullAccessManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04A9FE112EB4D0D20020DB6D /* KBFullAccessManager.m */; };
|
||||
04A9FE162EB873C80020DB6D /* UIViewController+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 04A9FE152EB873C80020DB6D /* UIViewController+Extension.m */; };
|
||||
@@ -221,6 +223,10 @@
|
||||
048908D82EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UICollectionViewLeftAlignedLayout.m; sourceTree = "<group>"; };
|
||||
048908DB2EBF67EB00FABA60 /* KBSearchResultVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSearchResultVC.h; sourceTree = "<group>"; };
|
||||
048908DC2EBF67EB00FABA60 /* KBSearchResultVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSearchResultVC.m; sourceTree = "<group>"; };
|
||||
048908DE2EBF73DC00FABA60 /* MySkinVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MySkinVC.h; sourceTree = "<group>"; };
|
||||
048908DF2EBF73DC00FABA60 /* MySkinVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MySkinVC.m; sourceTree = "<group>"; };
|
||||
048908E12EBF760000FABA60 /* MySkinCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MySkinCell.h; sourceTree = "<group>"; };
|
||||
048908E22EBF760000FABA60 /* MySkinCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MySkinCell.m; sourceTree = "<group>"; };
|
||||
04A9A67D2EB9E1690023B8F4 /* KBResponderUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBResponderUtils.h; sourceTree = "<group>"; };
|
||||
04A9FE102EB4D0D20020DB6D /* KBFullAccessManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFullAccessManager.h; sourceTree = "<group>"; };
|
||||
04A9FE112EB4D0D20020DB6D /* KBFullAccessManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFullAccessManager.m; sourceTree = "<group>"; };
|
||||
@@ -759,6 +765,8 @@
|
||||
04FC95BC2EB1E3B1007BD342 /* V */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
048908E12EBF760000FABA60 /* MySkinCell.h */,
|
||||
048908E22EBF760000FABA60 /* MySkinCell.m */,
|
||||
);
|
||||
path = V;
|
||||
sourceTree = "<group>";
|
||||
@@ -768,6 +776,8 @@
|
||||
children = (
|
||||
04FC95D02EB1E7AE007BD342 /* MyVC.h */,
|
||||
04FC95D12EB1E7AE007BD342 /* MyVC.m */,
|
||||
048908DE2EBF73DC00FABA60 /* MySkinVC.h */,
|
||||
048908DF2EBF73DC00FABA60 /* MySkinVC.m */,
|
||||
);
|
||||
path = VC;
|
||||
sourceTree = "<group>";
|
||||
@@ -1278,6 +1288,7 @@
|
||||
047C655E2EBCD5B20035E841 /* UIImage+KBColor.m in Sources */,
|
||||
04FC95DD2EB202A3007BD342 /* KBGuideVC.m in Sources */,
|
||||
04FC95E52EB220B5007BD342 /* UIColor+Extension.m in Sources */,
|
||||
048908E02EBF73DC00FABA60 /* MySkinVC.m in Sources */,
|
||||
0477BDF02EBB76E30055D639 /* HomeSheetVC.m in Sources */,
|
||||
04FC97002EB30A00007BD342 /* KBGuideTopCell.m in Sources */,
|
||||
0477BDFA2EBC66340055D639 /* HomeHeadView.m in Sources */,
|
||||
@@ -1308,6 +1319,7 @@
|
||||
047C65532EBCBAC60035E841 /* KBCommunityVC.m in Sources */,
|
||||
A1B2C4212EB4B7A100000001 /* KBKeyboardPermissionManager.m in Sources */,
|
||||
0459D1B42EBA284C00F2D189 /* KBSkinCenterVC.m in Sources */,
|
||||
048908E32EBF760000FABA60 /* MySkinCell.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
25
keyBoard/Class/Me/V/MySkinCell.h
Normal file
25
keyBoard/Class/Me/V/MySkinCell.h
Normal 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
|
||||
|
||||
186
keyBoard/Class/Me/V/MySkinCell.m
Normal file
186
keyBoard/Class/Me/V/MySkinCell.m
Normal 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
|
||||
16
keyBoard/Class/Me/VC/MySkinVC.h
Normal file
16
keyBoard/Class/Me/VC/MySkinVC.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// MySkinVC.h
|
||||
// keyBoard
|
||||
//
|
||||
// Created by Mac on 2025/11/8.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MySkinVC : UIViewController
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
256
keyBoard/Class/Me/VC/MySkinVC.m
Normal file
256
keyBoard/Class/Me/VC/MySkinVC.m
Normal file
@@ -0,0 +1,256 @@
|
||||
//
|
||||
// MySkinVC.m
|
||||
// keyBoard
|
||||
//
|
||||
// 我的皮肤列表页(支持编辑多选删除)。
|
||||
// 需求要点:
|
||||
// - 顶部右侧 Editor/Cancel 切换
|
||||
// - CollectionView Masonry 约束 + 懒加载控件
|
||||
// - 自定义 cell,编辑态显示左上角选择圆点,支持多选
|
||||
// - 底部 bottomView 展示已选择数量与删除按钮,数量>0 时 Delete 变为 #02BEAC 可点
|
||||
//
|
||||
|
||||
#import "MySkinVC.h"
|
||||
#import <Masonry/Masonry.h>
|
||||
#import "UIColor+Extension.h"
|
||||
|
||||
#import "MySkinCell.h"
|
||||
|
||||
static NSString * const kMySkinCellId = @"kMySkinCellId";
|
||||
|
||||
@interface MySkinVC () <UICollectionViewDataSource, UICollectionViewDelegate>
|
||||
@property (nonatomic, strong) UICollectionView *collectionView; // 列表
|
||||
@property (nonatomic, strong) UIView *bottomView; // 底部操作条
|
||||
@property (nonatomic, strong) UILabel *selectedLabel; // 已选择数量
|
||||
@property (nonatomic, strong) UIButton *deleteButton; // 删除
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray<NSDictionary *> *data; // 简单数据源
|
||||
@property (nonatomic, assign, getter=isEditingMode) BOOL editingMode; // 是否编辑态
|
||||
@end
|
||||
|
||||
@implementation MySkinVC
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
self.view.backgroundColor = [UIColor whiteColor];
|
||||
|
||||
self.title = @"My Skin"; // 标题
|
||||
|
||||
// 右上角 Editor/Cancel
|
||||
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Editor" style:UIBarButtonItemStylePlain target:self action:@selector(onToggleEdit)];
|
||||
|
||||
// 数据源(演示用)
|
||||
self.data = [@[
|
||||
@{ @"title": @"Dopamine" },
|
||||
@{ @"title": @"Dopamine" },
|
||||
@{ @"title": @"Dopamine" },
|
||||
@{ @"title": @"Dopamine" },
|
||||
] mutableCopy];
|
||||
|
||||
// 视图
|
||||
[self.view addSubview:self.collectionView];
|
||||
[self.view addSubview:self.bottomView];
|
||||
|
||||
[self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop);
|
||||
make.left.right.equalTo(self.view);
|
||||
make.bottom.equalTo(self.view.mas_bottom); // 底部被 bottomView 覆盖即可
|
||||
}];
|
||||
|
||||
[self.bottomView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.right.equalTo(self.view);
|
||||
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
|
||||
make.height.mas_equalTo(64);
|
||||
}];
|
||||
|
||||
// 初始:非编辑态,隐藏底部
|
||||
self.bottomView.hidden = YES;
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (void)onToggleEdit {
|
||||
self.editingMode = !self.editingMode;
|
||||
|
||||
// 更新顶部按钮
|
||||
self.navigationItem.rightBarButtonItem.title = self.isEditingMode ? @"Cancel" : @"Editor";
|
||||
|
||||
// 控制底部栏显隐
|
||||
self.bottomView.hidden = !self.isEditingMode;
|
||||
|
||||
// 列表进入/退出多选
|
||||
self.collectionView.allowsMultipleSelection = self.isEditingMode;
|
||||
// 直接刷新可见 cell,确保切换后立刻出现/隐藏 markView
|
||||
for (UICollectionViewCell *c in self.collectionView.visibleCells) {
|
||||
if (![c isKindOfClass:MySkinCell.class]) continue;
|
||||
MySkinCell *cell = (MySkinCell *)c;
|
||||
cell.editing = self.isEditingMode;
|
||||
NSIndexPath *ip = [self.collectionView indexPathForCell:cell];
|
||||
BOOL selected = [[self.collectionView indexPathsForSelectedItems] containsObject:ip];
|
||||
[cell updateSelected:selected];
|
||||
}
|
||||
// 再做一次 reload 保守刷新(防止 offscreen cell)
|
||||
[self.collectionView reloadData];
|
||||
|
||||
// 清空选择并刷新底部文案
|
||||
for (NSIndexPath *ip in [self.collectionView indexPathsForSelectedItems]) {
|
||||
[self.collectionView deselectItemAtIndexPath:ip animated:NO];
|
||||
}
|
||||
[self updateBottomUI];
|
||||
}
|
||||
|
||||
- (void)onDelete {
|
||||
// 根据选中项删除
|
||||
NSArray<NSIndexPath *> *selected = [[self.collectionView indexPathsForSelectedItems] sortedArrayUsingSelector:@selector(compare:)];
|
||||
if (selected.count == 0) return;
|
||||
|
||||
// 批量更新,先改数据,再删 UI
|
||||
[self.collectionView performBatchUpdates:^{
|
||||
NSMutableIndexSet *set = [NSMutableIndexSet indexSet];
|
||||
for (NSIndexPath *ip in selected) { [set addIndex:ip.item]; }
|
||||
[self.data removeObjectsAtIndexes:set];
|
||||
[self.collectionView deleteItemsAtIndexPaths:selected];
|
||||
} completion:^(BOOL finished) {
|
||||
[self updateBottomUI];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)updateBottomUI {
|
||||
NSInteger count = self.collectionView.indexPathsForSelectedItems.count;
|
||||
self.selectedLabel.text = [NSString stringWithFormat:@"Selected: %ld Skins", (long)count];
|
||||
|
||||
BOOL enable = count > 0;
|
||||
self.deleteButton.enabled = enable;
|
||||
if (enable) {
|
||||
self.deleteButton.backgroundColor = [UIColor colorWithHex:0x02BEAC];
|
||||
[self.deleteButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
|
||||
self.deleteButton.layer.borderColor = [UIColor colorWithHex:0x02BEAC].CGColor;
|
||||
} else {
|
||||
self.deleteButton.backgroundColor = [UIColor colorWithHex:0xF2F2F2];
|
||||
[self.deleteButton setTitleColor:[UIColor colorWithHex:0xC8C8C8] forState:UIControlStateNormal];
|
||||
self.deleteButton.layer.borderColor = [UIColor colorWithHex:0xE6E6E6].CGColor;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UICollectionView
|
||||
|
||||
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
|
||||
return self.data.count;
|
||||
}
|
||||
|
||||
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
MySkinCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kMySkinCellId forIndexPath:indexPath];
|
||||
NSDictionary *d = self.data[indexPath.item];
|
||||
[cell configWithTitle:d[@"title"] image:nil];
|
||||
cell.editing = self.isEditingMode; // 控制是否显示选择圆点
|
||||
// 同步选中状态(复用时)
|
||||
BOOL selected = [[collectionView indexPathsForSelectedItems] containsObject:indexPath];
|
||||
[cell updateSelected:selected];
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (!self.isEditingMode) {
|
||||
// 非编辑态:可在此进入详情,当前示例不处理
|
||||
[collectionView deselectItemAtIndexPath:indexPath animated:YES];
|
||||
return;
|
||||
}
|
||||
MySkinCell *cell = (MySkinCell *)[collectionView cellForItemAtIndexPath:indexPath];
|
||||
[cell updateSelected:YES];
|
||||
[self updateBottomUI];
|
||||
}
|
||||
|
||||
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (!self.isEditingMode) return;
|
||||
MySkinCell *cell = (MySkinCell *)[collectionView cellForItemAtIndexPath:indexPath];
|
||||
[cell updateSelected:NO];
|
||||
[self updateBottomUI];
|
||||
}
|
||||
|
||||
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (![cell isKindOfClass:MySkinCell.class]) return;
|
||||
MySkinCell *c = (MySkinCell *)cell;
|
||||
c.editing = self.isEditingMode; // 保证滚动出现的新 cell 同步编辑态
|
||||
BOOL selected = [[collectionView indexPathsForSelectedItems] containsObject:indexPath];
|
||||
[c updateSelected:selected];
|
||||
}
|
||||
|
||||
#pragma mark - Lazy
|
||||
|
||||
- (UICollectionView *)collectionView {
|
||||
if (!_collectionView) {
|
||||
UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new];
|
||||
CGFloat inset = 16;
|
||||
CGFloat spacing = 12;
|
||||
CGFloat W = UIScreen.mainScreen.bounds.size.width;
|
||||
CGFloat itemW = floor((W - inset * 2 - spacing) / 2.0);
|
||||
CGFloat itemH = itemW * 0.82f; // 接近截图比例
|
||||
layout.itemSize = CGSizeMake(itemW, itemH);
|
||||
layout.minimumInteritemSpacing = spacing;
|
||||
layout.minimumLineSpacing = spacing;
|
||||
layout.sectionInset = UIEdgeInsetsMake(12, inset, 12, inset);
|
||||
|
||||
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
|
||||
_collectionView.backgroundColor = [UIColor whiteColor];
|
||||
_collectionView.dataSource = self;
|
||||
_collectionView.delegate = self;
|
||||
_collectionView.allowsMultipleSelection = NO; // 初始
|
||||
[_collectionView registerClass:MySkinCell.class forCellWithReuseIdentifier:kMySkinCellId];
|
||||
}
|
||||
return _collectionView;
|
||||
}
|
||||
|
||||
- (UIView *)bottomView {
|
||||
if (!_bottomView) {
|
||||
_bottomView = [UIView new];
|
||||
_bottomView.backgroundColor = [UIColor whiteColor];
|
||||
_bottomView.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.06].CGColor;
|
||||
_bottomView.layer.shadowOpacity = 1;
|
||||
_bottomView.layer.shadowOffset = CGSizeMake(0, -2);
|
||||
|
||||
[_bottomView addSubview:self.selectedLabel];
|
||||
[_bottomView addSubview:self.deleteButton];
|
||||
|
||||
[self.selectedLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(_bottomView).offset(16);
|
||||
make.centerY.equalTo(_bottomView);
|
||||
}];
|
||||
[self.deleteButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.right.equalTo(_bottomView).offset(-16);
|
||||
make.centerY.equalTo(_bottomView);
|
||||
make.width.mas_equalTo(92);
|
||||
make.height.mas_equalTo(36);
|
||||
}];
|
||||
}
|
||||
return _bottomView;
|
||||
}
|
||||
|
||||
- (UILabel *)selectedLabel {
|
||||
if (!_selectedLabel) {
|
||||
_selectedLabel = [UILabel new];
|
||||
_selectedLabel.textColor = [UIColor colorWithHex:0x666666];
|
||||
_selectedLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium];
|
||||
_selectedLabel.text = @"Selected: 0 Skins";
|
||||
}
|
||||
return _selectedLabel;
|
||||
}
|
||||
|
||||
- (UIButton *)deleteButton {
|
||||
if (!_deleteButton) {
|
||||
_deleteButton = [UIButton buttonWithType:UIButtonTypeSystem];
|
||||
[_deleteButton setTitle:@"Delete" forState:UIControlStateNormal];
|
||||
_deleteButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold];
|
||||
_deleteButton.layer.cornerRadius = 18;
|
||||
_deleteButton.layer.borderWidth = 1;
|
||||
_deleteButton.clipsToBounds = YES;
|
||||
[_deleteButton addTarget:self action:@selector(onDelete) forControlEvents:UIControlEventTouchUpInside];
|
||||
// 初始禁用态样式
|
||||
_deleteButton.enabled = NO;
|
||||
_deleteButton.backgroundColor = [UIColor colorWithHex:0xF2F2F2];
|
||||
[_deleteButton setTitleColor:[UIColor colorWithHex:0xC8C8C8] forState:UIControlStateNormal];
|
||||
_deleteButton.layer.borderColor = [UIColor colorWithHex:0xE6E6E6].CGColor;
|
||||
}
|
||||
return _deleteButton;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -6,6 +6,7 @@
|
||||
//
|
||||
|
||||
#import "MyVC.h"
|
||||
#import "MySkinVC.h"
|
||||
|
||||
@interface MyVC ()
|
||||
|
||||
@@ -27,7 +28,8 @@
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
|
||||
[KBHUD show];
|
||||
MySkinVC *vc = [[MySkinVC alloc] init];
|
||||
[self.navigationController pushViewController:vc animated:true];
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user