From 5e1a1f540e69ba0acb9589a098a32c443f4ed81c Mon Sep 17 00:00:00 2001 From: CodeST <694468528@qq.com> Date: Sun, 9 Nov 2025 21:41:35 +0800 Subject: [PATCH] 1 --- keyBoard.xcodeproj/project.pbxproj | 34 ++++--- keyBoard/Class/Base/V/BaseTableView.h | 16 ++++ keyBoard/Class/Base/V/BaseTableView.m | 71 +++++++++++++++ .../Class/Base/V/UIScrollView+KBEmptyView.h | 40 +++++++++ .../Class/Base/V/UIScrollView+KBEmptyView.m | 90 +++++++++++++++++++ keyBoard/Class/Me/VC/KBSkinDetailVC.m | 8 -- keyBoard/Class/Me/VC/MySkinVC.m | 61 ++++++++++--- keyBoard/Class/Me/VC/MyVC.m | 6 +- keyBoard/Class/Shop/VC/KBShopItemVC.m | 1 - 9 files changed, 289 insertions(+), 38 deletions(-) create mode 100644 keyBoard/Class/Base/V/UIScrollView+KBEmptyView.h create mode 100644 keyBoard/Class/Base/V/UIScrollView+KBEmptyView.m diff --git a/keyBoard.xcodeproj/project.pbxproj b/keyBoard.xcodeproj/project.pbxproj index 775ebaf..8b4afcc 100644 --- a/keyBoard.xcodeproj/project.pbxproj +++ b/keyBoard.xcodeproj/project.pbxproj @@ -70,10 +70,11 @@ 048908EF2EBF861800FABA60 /* KBSkinSectionTitleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908EE2EBF861800FABA60 /* KBSkinSectionTitleCell.m */; }; 048908F22EC047FD00FABA60 /* KBShopHeadView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908F12EC047FD00FABA60 /* KBShopHeadView.m */; }; 048908F52EC0496400FABA60 /* KBShopItemVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908F42EC0496400FABA60 /* KBShopItemVC.m */; }; + 048908FE2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908FD2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.m */; }; 048909F62EC0AAAA00FABA60 /* KBCategoryTitleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048909F12EC0AAAA00FABA60 /* KBCategoryTitleCell.m */; }; 048909F72EC0AAAA00FABA60 /* KBCategoryTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048909F32EC0AAAA00FABA60 /* KBCategoryTitleView.m */; }; - 04890A042EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04890A012EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m */; }; - 04890A052EC0BBBB00FABA60 /* KBCategoryTitleImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04890A032EC0BBBB00FABA60 /* KBCategoryTitleImageView.m */; }; + 04890A042EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04890A012EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m */; }; + 04890A052EC0BBBB00FABA60 /* KBCategoryTitleImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04890A032EC0BBBB00FABA60 /* KBCategoryTitleImageView.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 */; }; @@ -252,14 +253,16 @@ 048908F12EC047FD00FABA60 /* KBShopHeadView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBShopHeadView.m; sourceTree = ""; }; 048908F32EC0496400FABA60 /* KBShopItemVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBShopItemVC.h; sourceTree = ""; }; 048908F42EC0496400FABA60 /* KBShopItemVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBShopItemVC.m; sourceTree = ""; }; + 048908FC2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+KBEmptyView.h"; sourceTree = ""; }; + 048908FD2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+KBEmptyView.m"; sourceTree = ""; }; 048909F02EC0AAAA00FABA60 /* KBCategoryTitleCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBCategoryTitleCell.h; sourceTree = ""; }; 048909F12EC0AAAA00FABA60 /* KBCategoryTitleCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBCategoryTitleCell.m; sourceTree = ""; }; 048909F22EC0AAAA00FABA60 /* KBCategoryTitleView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBCategoryTitleView.h; sourceTree = ""; }; 048909F32EC0AAAA00FABA60 /* KBCategoryTitleView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBCategoryTitleView.m; sourceTree = ""; }; - 04890A002EC0BBBB00FABA60 /* KBCategoryTitleImageCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBCategoryTitleImageCell.h; sourceTree = ""; }; - 04890A012EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBCategoryTitleImageCell.m; sourceTree = ""; }; - 04890A022EC0BBBB00FABA60 /* KBCategoryTitleImageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBCategoryTitleImageView.h; sourceTree = ""; }; - 04890A032EC0BBBB00FABA60 /* KBCategoryTitleImageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBCategoryTitleImageView.m; sourceTree = ""; }; + 04890A002EC0BBBB00FABA60 /* KBCategoryTitleImageCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBCategoryTitleImageCell.h; sourceTree = ""; }; + 04890A012EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBCategoryTitleImageCell.m; sourceTree = ""; }; + 04890A022EC0BBBB00FABA60 /* KBCategoryTitleImageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBCategoryTitleImageView.h; sourceTree = ""; }; + 04890A032EC0BBBB00FABA60 /* KBCategoryTitleImageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBCategoryTitleImageView.m; sourceTree = ""; }; 04A9A67D2EB9E1690023B8F4 /* KBResponderUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBResponderUtils.h; sourceTree = ""; }; 04A9FE102EB4D0D20020DB6D /* KBFullAccessManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFullAccessManager.h; sourceTree = ""; }; 04A9FE112EB4D0D20020DB6D /* KBFullAccessManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFullAccessManager.m; sourceTree = ""; }; @@ -506,10 +509,10 @@ 048909F12EC0AAAA00FABA60 /* KBCategoryTitleCell.m */, 048909F22EC0AAAA00FABA60 /* KBCategoryTitleView.h */, 048909F32EC0AAAA00FABA60 /* KBCategoryTitleView.m */, - 04890A002EC0BBBB00FABA60 /* KBCategoryTitleImageCell.h */, - 04890A012EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m */, - 04890A022EC0BBBB00FABA60 /* KBCategoryTitleImageView.h */, - 04890A032EC0BBBB00FABA60 /* KBCategoryTitleImageView.m */, + 04890A002EC0BBBB00FABA60 /* KBCategoryTitleImageCell.h */, + 04890A012EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m */, + 04890A022EC0BBBB00FABA60 /* KBCategoryTitleImageView.h */, + 04890A032EC0BBBB00FABA60 /* KBCategoryTitleImageView.m */, ); path = V; sourceTree = ""; @@ -883,6 +886,8 @@ 04FC95D42EB1EA16007BD342 /* BaseCell.m */, 04FC95D52EB1EA16007BD342 /* BaseTableView.h */, 04FC95D62EB1EA16007BD342 /* BaseTableView.m */, + 048908FC2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.h */, + 048908FD2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.m */, ); path = V; sourceTree = ""; @@ -1249,10 +1254,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks.sh\"\n"; @@ -1316,8 +1325,8 @@ files = ( 048909F62EC0AAAA00FABA60 /* KBCategoryTitleCell.m in Sources */, 048909F72EC0AAAA00FABA60 /* KBCategoryTitleView.m in Sources */, - 04890A042EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m in Sources */, - 04890A052EC0BBBB00FABA60 /* KBCategoryTitleImageView.m in Sources */, + 04890A042EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m in Sources */, + 04890A052EC0BBBB00FABA60 /* KBCategoryTitleImageView.m in Sources */, 04FC95E92EB23B67007BD342 /* KBNetworkManager.m in Sources */, 04FC95D22EB1E7AE007BD342 /* MyVC.m in Sources */, 047C65582EBCC06D0035E841 /* HomeRankCardCell.m in Sources */, @@ -1357,6 +1366,7 @@ 04FC97062EB30A00007BD342 /* KBGuideUserCell.m in Sources */, 04FC97092EB31B14007BD342 /* KBHUD.m in Sources */, 04FC970E2EB334F8007BD342 /* UIImageView+KBWebImage.m in Sources */, + 048908FE2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.m in Sources */, 04FC970F2EB334F8007BD342 /* KBWebImageManager.m in Sources */, 04FC95CF2EB1E7A1007BD342 /* HomeVC.m in Sources */, A1B2D7022EB8C00100000001 /* KBLangTestVC.m in Sources */, diff --git a/keyBoard/Class/Base/V/BaseTableView.h b/keyBoard/Class/Base/V/BaseTableView.h index 9395838..b6777a7 100644 --- a/keyBoard/Class/Base/V/BaseTableView.h +++ b/keyBoard/Class/Base/V/BaseTableView.h @@ -40,6 +40,22 @@ typedef void(^KBEmptyAction)(void); /// 触发刷新空数据视图(若集成了 DZNEmptyDataSet 则调用其 reloadEmptyDataSet) - (void)kb_reloadEmptyDataSet; +/// 使用 LYEmptyView 在表格页快速挂载一套统一样式的空态视图(与 DZNEmptyDataSet 二选一) +/// 注意:调用该方法会自动关闭本类内置的 DZNEmptyDataSet(useEmptyDataSet = NO),避免冲突。 +/// - Parameters: +/// - image: 占位图(可空) +/// - title: 标题(默认“暂无数据”) +/// - detail: 描述(可空) +/// - buttonTitle: 按钮标题(可空,传空则不展示按钮) +/// - tapHandler: 点击空白区域回调(可空) +/// - buttonHandler: 按钮点击回调(可空) +- (void)kb_makeDefaultEmptyViewWithImage:(nullable UIImage *)image + title:(nullable NSString *)title + detail:(nullable NSString *)detail + buttonTitle:(nullable NSString *)buttonTitle + tapHandler:(nullable KBEmptyAction)tapHandler + buttonHandler:(nullable KBEmptyAction)buttonHandler; + @end NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Base/V/BaseTableView.m b/keyBoard/Class/Base/V/BaseTableView.m index 0d743e3..ff1e49f 100644 --- a/keyBoard/Class/Base/V/BaseTableView.m +++ b/keyBoard/Class/Base/V/BaseTableView.m @@ -13,6 +13,15 @@ #define KB_HAS_DZN 0 #endif +// 可选引入:LYEmptyView(通过 Pod 集成),用于空态视图的“自动显隐+属性配置”方案 +#if __has_include() +#import +#import +#define KB_HAS_LY 1 +#else +#define KB_HAS_LY 0 +#endif + @interface BaseTableView () #if KB_HAS_DZN @@ -127,4 +136,66 @@ #endif +// MARK: - LYEmptyView 快速挂载(与 DZN 二选一) +- (void)kb_makeDefaultEmptyViewWithImage:(UIImage *)image + title:(NSString *)title + detail:(NSString *)detail + buttonTitle:(NSString *)buttonTitle + tapHandler:(KBEmptyAction)tapHandler + buttonHandler:(KBEmptyAction)buttonHandler { +#if KB_HAS_LY + // 关闭 DZN,避免两套空态叠加 + self.useEmptyDataSet = NO; + + // 默认文案 + NSString *t = title ?: @"暂无数据"; + + LYEmptyView *ev = nil; + if (buttonTitle.length > 0) { + // 带按钮(优先 block 方式) + __weak typeof(self) weakSelf = self; + ev = [LYEmptyView emptyActionViewWithImage:image + titleStr:t + detailStr:detail ?: @"" + btnTitleStr:buttonTitle + btnClickBlock:^{ if (buttonHandler) buttonHandler(); [weakSelf setNeedsLayout]; }]; + } else { + // 无按钮 + ev = [LYEmptyView emptyViewWithImage:image titleStr:t detailStr:detail ?: @""]; + } + + // 点击空白区域 + if (tapHandler) { + ev.tapEmptyViewBlock = ^{ tapHandler(); }; + } + + // 统一样式(可按需微调) + ev.emptyViewIsCompleteCoverSuperView = NO; // 不全屏覆盖,按内容大小布局 + ev.ignoreContentInset = YES; // 忽略 inset,避免导航/安全区影响 + ev.contentViewOffset = -10; // 轻微上移 + ev.subViewMargin = 14; // 子控件间距 + ev.titleLabFont = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + ev.titleLabTextColor = [UIColor colorWithWhite:0.45 alpha:1.0]; + ev.detailLabFont = [UIFont systemFontOfSize:14]; + ev.detailLabTextColor = [UIColor colorWithWhite:0.6 alpha:1.0]; + ev.detailLabLineSpacing = 3; + ev.detailLabMaxLines = 2; + ev.actionBtnFont = [UIFont systemFontOfSize:15 weight:UIFontWeightSemibold]; + ev.actionBtnCornerRadius = 6; + ev.actionBtnBorderWidth = 1; + ev.actionBtnBorderColor = [UIColor colorWithWhite:0.88 alpha:1.0]; + ev.actionBtnTitleColor = [UIColor colorWithRed:0.22 green:0.49 blue:0.96 alpha:1.0]; + ev.actionBtnBackGroundColor = [UIColor whiteColor]; + ev.actionBtnHorizontalMargin = 20; // 自动宽度:文字 + padding*2 + + // 自动显隐交由控制层(网络请求) + ev.autoShowEmptyView = NO; + + self.ly_emptyView = (LYEmptyView *)ev; +#else + // 未集成 LYEmptyView 时不做任何处理,保持兼容 + (void)image; (void)title; (void)detail; (void)buttonTitle; (void)tapHandler; (void)buttonHandler; +#endif +} + @end diff --git a/keyBoard/Class/Base/V/UIScrollView+KBEmptyView.h b/keyBoard/Class/Base/V/UIScrollView+KBEmptyView.h new file mode 100644 index 0000000..c1b15ae --- /dev/null +++ b/keyBoard/Class/Base/V/UIScrollView+KBEmptyView.h @@ -0,0 +1,40 @@ +// +// UIScrollView+KBEmptyView.h +// keyBoard +// +// 统一封装基于 LYEmptyView 的空态视图挂载方法,适用于 UITableView/UICollectionView。 +// 注意:仅在对应页面已通过 CocoaPods 集成 LYEmptyView 时生效。 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef void(^KBEmptyAction)(void); + +@interface UIScrollView (KBEmptyView) + +/// 快速挂载一套统一样式的空态视图(LYEmptyView) +/// - Parameters: +/// - image: 占位图(可空) +/// - title: 标题(默认“暂无数据”) +/// - detail: 描述(可空) +/// - buttonTitle: 按钮标题(可空,传空则不显示按钮) +/// - tapHandler: 点击空白区域回调(可空) +/// - buttonHandler: 按钮点击回调(可空) +- (void)kb_makeDefaultEmptyViewWithImage:(nullable UIImage *)image + title:(nullable NSString *)title + detail:(nullable NSString *)detail + buttonTitle:(nullable NSString *)buttonTitle + tapHandler:(nullable KBEmptyAction)tapHandler + buttonHandler:(nullable KBEmptyAction)buttonHandler; + +/// 便捷加载态控制:关闭自动显隐后,配合网络请求手动控制显示/隐藏 +- (void)kb_setLYAutoShowEnabled:(BOOL)enabled; // YES=自动显隐;NO=手动 +- (void)kb_beginLoadingForEmpty; // 请求开始:临时隐藏 empty +- (void)kb_endLoadingForEmpty; // 请求结束:根据数据源显示/隐藏(需确保先 reloadData) + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Base/V/UIScrollView+KBEmptyView.m b/keyBoard/Class/Base/V/UIScrollView+KBEmptyView.m new file mode 100644 index 0000000..3c75ad2 --- /dev/null +++ b/keyBoard/Class/Base/V/UIScrollView+KBEmptyView.m @@ -0,0 +1,90 @@ +// +// UIScrollView+KBEmptyView.m +// keyBoard +// + +#import "UIScrollView+KBEmptyView.h" + +#if __has_include() +#import +#import +#define KB_HAS_LY 1 +#else +#define KB_HAS_LY 0 +#endif + +@implementation UIScrollView (KBEmptyView) + +- (void)kb_makeDefaultEmptyViewWithImage:(UIImage *)image + title:(NSString *)title + detail:(NSString *)detail + buttonTitle:(NSString *)buttonTitle + tapHandler:(KBEmptyAction)tapHandler + buttonHandler:(KBEmptyAction)buttonHandler { +#if KB_HAS_LY + NSString *t = title ?: @"暂无数据"; + LYEmptyView *ev = nil; + + if (buttonTitle.length > 0) { + __weak typeof(self) weakSelf = self; + ev = [LYEmptyView emptyActionViewWithImage:image + titleStr:t + detailStr:detail ?: @"" + btnTitleStr:buttonTitle + btnClickBlock:^{ if (buttonHandler) buttonHandler(); [weakSelf setNeedsLayout]; }]; + } else { + ev = [LYEmptyView emptyViewWithImage:image titleStr:t detailStr:detail ?: @""]; + } + + if (tapHandler) { ev.tapEmptyViewBlock = ^{ tapHandler(); }; } + + // 统一样式 + ev.emptyViewIsCompleteCoverSuperView = NO; + ev.ignoreContentInset = YES; + ev.contentViewOffset = -10; + ev.subViewMargin = 14; + ev.titleLabFont = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + ev.titleLabTextColor = [UIColor colorWithWhite:0.45 alpha:1.0]; + ev.detailLabFont = [UIFont systemFontOfSize:14]; + ev.detailLabTextColor = [UIColor colorWithWhite:0.6 alpha:1.0]; + ev.detailLabLineSpacing = 3; + ev.detailLabMaxLines = 2; + ev.actionBtnFont = [UIFont systemFontOfSize:15 weight:UIFontWeightSemibold]; + ev.actionBtnCornerRadius = 6; + ev.actionBtnBorderWidth = 1; + ev.actionBtnBorderColor = [UIColor colorWithWhite:0.88 alpha:1.0]; + ev.actionBtnTitleColor = [UIColor colorWithRed:0.22 green:0.49 blue:0.96 alpha:1.0]; + ev.actionBtnBackGroundColor = [UIColor whiteColor]; + ev.actionBtnHorizontalMargin = 20; + + // 默认关闭自动显隐,交给调用方用 begin/end 控制 + ev.autoShowEmptyView = NO; + + self.ly_emptyView = ev; +#else + (void)image; (void)title; (void)detail; (void)buttonTitle; (void)tapHandler; (void)buttonHandler; +#endif +} + +- (void)kb_setLYAutoShowEnabled:(BOOL)enabled { +#if KB_HAS_LY + self.ly_emptyView.autoShowEmptyView = enabled; +#else + (void)enabled; +#endif +} + +- (void)kb_beginLoadingForEmpty { +#if KB_HAS_LY + [self ly_startLoading]; +#endif +} + +- (void)kb_endLoadingForEmpty { +#if KB_HAS_LY + [self ly_endLoading]; +#endif +} + +@end + diff --git a/keyBoard/Class/Me/VC/KBSkinDetailVC.m b/keyBoard/Class/Me/VC/KBSkinDetailVC.m index 4670012..10e002b 100644 --- a/keyBoard/Class/Me/VC/KBSkinDetailVC.m +++ b/keyBoard/Class/Me/VC/KBSkinDetailVC.m @@ -1,14 +1,6 @@ // // KBSkinDetailVC.m // keyBoard -// -// 皮肤详情页(UICollectionView 实现) -// 结构: -// - Section0:顶部大卡片(上图,下方左右两段文案) -// - Section1:标签容器 cell(内部再嵌套一个 collectionView 以展示 Cute/Fresh 等标签) -// - Section2:区块标题 cell(例如 “Recommended Skin”) -// - Section3:推荐皮肤 2 列网格(使用已有 KBSkinCardCell) -// #import "KBSkinDetailVC.h" #import diff --git a/keyBoard/Class/Me/VC/MySkinVC.m b/keyBoard/Class/Me/VC/MySkinVC.m index 41bc318..b700196 100644 --- a/keyBoard/Class/Me/VC/MySkinVC.m +++ b/keyBoard/Class/Me/VC/MySkinVC.m @@ -2,17 +2,12 @@ // MySkinVC.m // keyBoard // -// 我的皮肤列表页(支持编辑多选删除)。 -// 需求要点: -// - 顶部右侧 Editor/Cancel 切换 -// - CollectionView Masonry 约束 + 懒加载控件 -// - 自定义 cell,编辑态显示左上角选择圆点,支持多选 -// - 底部 bottomView 展示已选择数量与删除按钮,数量>0 时 Delete 变为 #02BEAC 可点 -// #import "MySkinVC.h" #import #import "UIColor+Extension.h" +#import +#import "UIScrollView+KBEmptyView.h" // 统一空态封装(LYEmptyView) #import "MySkinCell.h" @@ -25,6 +20,7 @@ static NSString * const kMySkinCellId = @"kMySkinCellId"; @property (nonatomic, strong) UIButton *deleteButton; // 删除 @property (nonatomic, strong) NSMutableArray *data; // 简单数据源 +@property (nonatomic, assign) NSInteger loadCount; // 刷新计数(用于演示空/有数据切换) @property (nonatomic, assign, getter=isEditingMode) BOOL editingMode; // 是否编辑态 @end @@ -39,13 +35,8 @@ static NSString * const kMySkinCellId = @"kMySkinCellId"; // 右上角 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.data = [NSMutableArray array]; // 视图 [self.view addSubview:self.collectionView]; @@ -63,10 +54,50 @@ static NSString * const kMySkinCellId = @"kMySkinCellId"; make.height.mas_equalTo(64); }]; + // 空态视图(LYEmptyView)统一样式 + 重试按钮 + __weak typeof(self) weakSelf = self; + [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 { @@ -112,6 +143,8 @@ static NSString * const kMySkinCellId = @"kMySkinCellId"; [self.collectionView deleteItemsAtIndexPaths:selected]; } completion:^(BOOL finished) { [self updateBottomUI]; + // 根据当前数据源显隐空视图(删除到 0 条时应显示空态) + [self.collectionView kb_endLoadingForEmpty]; }]; } diff --git a/keyBoard/Class/Me/VC/MyVC.m b/keyBoard/Class/Me/VC/MyVC.m index a422724..d977520 100644 --- a/keyBoard/Class/Me/VC/MyVC.m +++ b/keyBoard/Class/Me/VC/MyVC.m @@ -29,10 +29,10 @@ } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ -// MySkinVC *vc = [[MySkinVC alloc] init]; - KBSkinDetailVC *vc = [[KBSkinDetailVC alloc] init]; + MySkinVC *vc = [[MySkinVC alloc] init]; +// KBSkinDetailVC *vc = [[KBSkinDetailVC alloc] init]; -// [self.navigationController pushViewController:vc animated:true]; + [self.navigationController pushViewController:vc animated:true]; } /* diff --git a/keyBoard/Class/Shop/VC/KBShopItemVC.m b/keyBoard/Class/Shop/VC/KBShopItemVC.m index 89da023..55e252f 100644 --- a/keyBoard/Class/Shop/VC/KBShopItemVC.m +++ b/keyBoard/Class/Shop/VC/KBShopItemVC.m @@ -10,7 +10,6 @@ #import #import "KBSkinCardCell.h" -/// 商城列表:使用 UICollectionView,两列网格,复用 KBSkinCardCell @interface KBShopItemVC () @property (nonatomic, copy) void(^scrollCallback)(UIScrollView *scrollView); @end