Files
keyboard/keyBoard/Class/Me/VC/MySkinVC.m
2025-11-17 14:53:23 +08:00

297 lines
12 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// MySkinVC.m
// keyBoard
//
#import "MySkinVC.h"
#import "KBSkinDetailVC.h"
#import <Masonry/Masonry.h>
#import "UIColor+Extension.h"
#import <MJRefresh/MJRefresh.h>
#import "UIScrollView+KBEmptyView.h" // 统一空态封装LYEmptyView
#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) NSInteger loadCount; // 刷新计数(用于演示空/有数据切换)
@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 使用 BaseViewController 自定义导航栏的 kb_rightButton
self.kb_rightButton.hidden = NO;
[self.kb_rightButton setTitle:@"Editor" forState:UIControlStateNormal];
[self.kb_rightButton removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents];
[self.kb_rightButton addTarget:self action:@selector(onToggleEdit) forControlEvents:UIControlEventTouchUpInside];
// 数据源初始化为空(演示空态 + 下拉刷新)
self.data = [NSMutableArray array];
// 视图
[self.view addSubview:self.collectionView];
[self.view addSubview:self.bottomView];
[self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view).offset(KB_NAV_TOTAL_HEIGHT);
make.left.right.equalTo(self.view);
make.bottom.equalTo(self.view.mas_bottom);
}];
[self.bottomView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.view);
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
make.height.mas_equalTo(64);
}];
// 空态视图LYEmptyView统一样式 + 重试按钮
KBWeakSelf
[self.collectionView kb_makeDefaultEmptyViewWithImage:nil
title:@"暂无皮肤"
detail:@"下拉刷新试试"
buttonTitle:@"重试"
tapHandler:nil
buttonHandler:^{ [weakSelf.collectionView.mj_header beginRefreshing]; }];
[self.collectionView kb_setLYAutoShowEnabled:NO]; // 采用手动控制显隐
// 立即按当前数据源状态显示一次空态(首屏就应展示空视图)
[self.collectionView kb_endLoadingForEmpty];
// 下拉刷新(演示网络加载 + 空态切换)
self.collectionView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(fetchData)];
// 首次进入自动刷新
[self.collectionView.mj_header beginRefreshing];
// 初始:非编辑态,隐藏底部
self.bottomView.hidden = YES;
}
#pragma mark - Data
- (void)fetchData {
// 模拟网络延迟 1.0s
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.loadCount += 1;
// 交替返回:奇数次空数据,偶数次有数据(演示空态/非空切换)
[self.data removeAllObjects];
if (self.loadCount % 2 == 0) {
for (int i = 0; i < 8; i++) {
[self.data addObject:@{ @"title": @"Dopamine" }];
}
}
[self.collectionView reloadData];
[self.collectionView kb_endLoadingForEmpty]; // 根据数据源显示/隐藏 emptyView
[self.collectionView.mj_header endRefreshing];
});
}
#pragma mark - Actions
- (void)onToggleEdit {
self.editingMode = !self.editingMode;
// 更新顶部按钮
[self.kb_rightButton setTitle:(self.isEditingMode ? @"Cancel" : @"Editor")
forState:UIControlStateNormal];
// 控制底部栏显隐
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];
// 根据当前数据源显隐空视图(删除到 0 条时应显示空态)
[self.collectionView kb_endLoadingForEmpty];
}];
}
- (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:KBColorValue];
[self.deleteButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
self.deleteButton.layer.borderColor = [UIColor colorWithHex:KBColorValue].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];
KBSkinDetailVC *vc = [[KBSkinDetailVC alloc] init];
[self.navigationController pushViewController:vc animated:true];
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