From 57bd4ba1092c45ac7a147a5ad6053fb7f988fca4 Mon Sep 17 00:00:00 2001 From: CodeST <694468528@qq.com> Date: Tue, 11 Nov 2025 14:38:38 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=BC=B9=E7=AA=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- keyBoard.xcodeproj/project.pbxproj | 12 +- .../white_close_icon.imageset/Contents.json | 22 ++ .../white_close_icon@2x.png | Bin 0 -> 2307 bytes .../white_close_icon@3x.png | Bin 0 -> 4350 bytes keyBoard/Class/Home/V/HomeRankDetailPopView.h | 29 +++ keyBoard/Class/Home/V/HomeRankDetailPopView.m | 241 ++++++++++++++++++ keyBoard/Class/Home/VC/HomeRankContentVC.m | 38 ++- keyBoard/KeyBoardPrefixHeader.pch | 4 +- 8 files changed, 338 insertions(+), 8 deletions(-) create mode 100644 keyBoard/Assets.xcassets/Home/white_close_icon.imageset/Contents.json create mode 100644 keyBoard/Assets.xcassets/Home/white_close_icon.imageset/white_close_icon@2x.png create mode 100644 keyBoard/Assets.xcassets/Home/white_close_icon.imageset/white_close_icon@3x.png create mode 100644 keyBoard/Class/Home/V/HomeRankDetailPopView.h create mode 100644 keyBoard/Class/Home/V/HomeRankDetailPopView.m diff --git a/keyBoard.xcodeproj/project.pbxproj b/keyBoard.xcodeproj/project.pbxproj index 7e4dd31..cbbd385 100644 --- a/keyBoard.xcodeproj/project.pbxproj +++ b/keyBoard.xcodeproj/project.pbxproj @@ -81,6 +81,8 @@ 049FB2112EC1F72F00FAB05D /* KBMyListCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB2102EC1F72F00FAB05D /* KBMyListCell.m */; }; 049FB2172EC20A6600FAB05D /* BMLongPressDragCellCollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB2132EC20A6600FAB05D /* BMLongPressDragCellCollectionView.m */; }; 049FB21A2EC20A9E00FAB05D /* KBMyKeyBoardVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB2192EC20A9E00FAB05D /* KBMyKeyBoardVC.m */; }; + 049FB2202EC30D2700FAB05D /* HomeRankDetailPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB21F2EC30D2700FAB05D /* HomeRankDetailPopView.m */; }; + 049FB31D2EC21BCD00FAB05D /* KBMyKeyboardCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB31C2EC21BCD00FAB05D /* KBMyKeyboardCell.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 */; }; @@ -135,7 +137,6 @@ A1B2E1012EBC7AAA00000001 /* KBTopThreeView.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2E0022EBC7AAA00000001 /* KBTopThreeView.m */; }; A1B2E1022EBC7AAA00000001 /* HomeHotCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2E0042EBC7AAA00000001 /* HomeHotCell.m */; }; ECC9EE02174D86E8D792472F /* Pods_keyBoard.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 967065BB5230E43F293B3AF9 /* Pods_keyBoard.framework */; }; - 049FB31D2EC21BCD00FAB05D /* KBMyKeyboardCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB31C2EC21BCD00FAB05D /* KBMyKeyboardCell.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -284,8 +285,10 @@ 049FB2152EC20A6600FAB05D /* BMLongPressDragCellCollectionViewDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BMLongPressDragCellCollectionViewDelegate.h; sourceTree = ""; }; 049FB2182EC20A9E00FAB05D /* KBMyKeyBoardVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBMyKeyBoardVC.h; sourceTree = ""; }; 049FB2192EC20A9E00FAB05D /* KBMyKeyBoardVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBMyKeyBoardVC.m; sourceTree = ""; }; - 049FB31B2EC21BCD00FAB05D /* KBMyKeyboardCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBMyKeyboardCell.h; sourceTree = ""; }; - 049FB31C2EC21BCD00FAB05D /* KBMyKeyboardCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBMyKeyboardCell.m; sourceTree = ""; }; + 049FB21E2EC30D2700FAB05D /* HomeRankDetailPopView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeRankDetailPopView.h; sourceTree = ""; }; + 049FB21F2EC30D2700FAB05D /* HomeRankDetailPopView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeRankDetailPopView.m; sourceTree = ""; }; + 049FB31B2EC21BCD00FAB05D /* KBMyKeyboardCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBMyKeyboardCell.h; sourceTree = ""; }; + 049FB31C2EC21BCD00FAB05D /* KBMyKeyboardCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBMyKeyboardCell.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 = ""; }; @@ -779,6 +782,8 @@ 047C650C2EBC8A840035E841 /* KBPanModalView.m */, 047C65562EBCC06D0035E841 /* HomeRankCardCell.h */, 047C65572EBCC06D0035E841 /* HomeRankCardCell.m */, + 049FB21E2EC30D2700FAB05D /* HomeRankDetailPopView.h */, + 049FB21F2EC30D2700FAB05D /* HomeRankDetailPopView.m */, ); path = V; sourceTree = ""; @@ -1443,6 +1448,7 @@ 0477BDFD2EBC6A170055D639 /* HomeHotVC.m in Sources */, 048908CC2EBE373500FABA60 /* KBSearchBarView.m in Sources */, 048908CD2EBE373500FABA60 /* KBSearchSectionHeader.m in Sources */, + 049FB2202EC30D2700FAB05D /* HomeRankDetailPopView.m in Sources */, 048908CE2EBE373500FABA60 /* KBSkinCardCell.m in Sources */, 048908CF2EBE373500FABA60 /* KBTagCell.m in Sources */, 0477BEA22EBCF0000055D639 /* KBTopImageButton.m in Sources */, diff --git a/keyBoard/Assets.xcassets/Home/white_close_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/white_close_icon.imageset/Contents.json new file mode 100644 index 0000000..ea55260 --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/white_close_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "white_close_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "white_close_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/white_close_icon.imageset/white_close_icon@2x.png b/keyBoard/Assets.xcassets/Home/white_close_icon.imageset/white_close_icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ace3ad2683e537c3ba16810beb01561734094317 GIT binary patch literal 2307 zcmV+e3H7{~8j`@EHnkNsS#64_ zwJ6h8Bde{p+RDnxYCfNL=bW8;_P+PN@BQ81Z~OH;_dMr0&w0-CJ?FgVJ?HnHS-lDW z9Y212HhdlY61)oj9^L~Vfd7O4g%82IV9T_59@#pxCmc?1A^-{QEci}%H31%ge}UhJ zpM)2{m%!)30yv9wE<6vmOq*rM*0B@5!jHbRMLji|5zq8NLg?488z9JFxN<$oIetVQmkR)=>odYiPU9rcu`#AkH1N6?k&`_)H-Vkf1(B zb7Q~XKd0aC-`nr^m%^Li-SB?+NMPli$X~-t;Crbj=$lFPp)bS%@|oR894p|ajvc6A zrWHUOUWoBl_*uB5{U~05FD1~Y;Gd8?6ZMY4Kfq5>`BK>FSqIb@wuYE68%`qu;^<;r z2=02)oQ{$C2)>MVrg3TFtr(i&49 z&a)x*TsJs^7&tXuwQ?gL?uY2P(>8K>Fv=koN7C3-MP3;&#QY#Yw6DUxP)RCsd43Rw z&i_hrru>AM-1{1149n;7wU{wYQxxQGiF{$JkGv8`GqzgBM%$(#Hg`UGm6rpSN|ykV zdma`fNkxvDFWV~9^ni=Rxb>D$!f`Zaa&tR4z7m;Cr?scnzibH1puuY2^%obOuQP!@!MP;D|dB zF&MKW8Fga1Mu0xhQE9pjKyvw?KebKr*QjX-LLHcs1*+d5gSe}Y6PsL*jfV+>X?hOTiSdrj7ptjx&RJFSOl(Fv> z;O@f5{372e8^HOWuY6io;8=9l!LFFo1+t8Nw*borz1+IB1~>{_bTo}1Z;Wk(^fv*X zvVRMOoszcTqSFAXaU9;h}wJOgT8)1h@mw`AX^`^9FRS3Fkg@jnlHp5g?aR zHs$jqJ|tt#H!Wh?F^figK0HZl6xq+pQ68EC?qLi{aK7X2!uLALh7vYz(V9S3r}Ci= zP8ODj_RaXN-h-Ny|NFR~z{@39yE^v&s7{YqCb)ZW{%ur@O0jJMSsr3*U4>Zv^qrSi zhjyo^%J2B`pi5Gb;2x`_(Lc_BXw?~9tk?kZe1gwAFPfLB|3x$AsCRl+9b5s#xq+>W zr6FC2^ENMir}JLw_`2yda?}|h;&3Egcw(n5Mi=D)+n6Cnft9Zv|07t{s{jUL-%kP! z+1~jGwI4LlCn5kpQC~#rhtR6mQsEc^eq4C`oP8ehJ1tyz%R`XS)X@`5l}`Y1W`TEG zs)F$IBt7Kn6tXju5X(V%RBIu&@SR(2&|*OPZu2&vsjA3MjqNlz zW2-A|`C(=|0oXQ4B4b++Vol0iXauMc75^f2hi)$+Ci3C-j>-o#ZqKHINecL$1AmB5 zPdv7Xn8=vCt7D8wSqeh|Y8*h`g6upeN#rZU9YnkhI5D7r@1(29UO3O|SJ^+;c+hyx^0_oaRx*hio)Mz50I4bO+&I6LKJ<$375+3VG3Z4cqi z?;`rp7uf-FN_qr)jyP%;lmY9IX$>&g_i*mJ=4$eeTG|qk&&h+QcR~HM?0?q0U+U%A ze=w4joqk@;bbF|69VpCuf?14kMQ9tbJ#_}CYZ`Ji-T8YPa2Qa{$7PRi`o4hn-hc(# z+1FSAV=FZ3Z9svZht8?%zY3d16_X)!qR6`LFZJaKWsz;1C>rl~N&sV%1mR^?k4+Dt z6RbBbTwy(tyTtp<8oZ<6InB}WnX*h9&w$qPh~%v*eQArksnP!c00960z^tC=00006 dNkl{ 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 literal 0 HcmV?d00001 diff --git a/keyBoard/Class/Home/V/HomeRankDetailPopView.h b/keyBoard/Class/Home/V/HomeRankDetailPopView.h new file mode 100644 index 0000000..b02ca6d --- /dev/null +++ b/keyBoard/Class/Home/V/HomeRankDetailPopView.h @@ -0,0 +1,29 @@ +// +// HomeRankDetailPopView.h +// keyBoard +// +// Created by Codex on 2025/11/11. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// 排行榜详情弹窗的自定义内容视图(给 LSTPopView 使用) +@interface HomeRankDetailPopView : UIView + +/// 保存按钮点击回调 +@property (nonatomic, copy, nullable) void (^saveHandler)(void); +/// 关闭按钮点击回调(底部圆形 X) +@property (nonatomic, copy, nullable) void (^closeHandler)(void); + +/// 配置数据 +- (void)configWithAvatar:(UIImage *_Nullable)avatar + title:(NSString *)title + download:(NSString *)download + desc:(NSString *)desc; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Home/V/HomeRankDetailPopView.m b/keyBoard/Class/Home/V/HomeRankDetailPopView.m new file mode 100644 index 0000000..129ceb7 --- /dev/null +++ b/keyBoard/Class/Home/V/HomeRankDetailPopView.m @@ -0,0 +1,241 @@ +// +// HomeRankDetailPopView.m +// keyBoard +// +// Created by Codex on 2025/11/11. +// + +@import UIKit; +#import "HomeRankDetailPopView.h" +#import + +@interface HomeRankDetailPopView () + +// 容器卡片(白底圆角) +@property (nonatomic, strong) UIView *cardView; +// 头像(圆形,带白色描边) +@property (nonatomic, strong) UIImageView *avatarView; +// 标题 +@property (nonatomic, strong) UILabel *titleLabel; +// 下载人数文案(绿色) +@property (nonatomic, strong) UILabel *downloadLabel; +// 内容气泡容器 +@property (nonatomic, strong) UIView *bubbleView; +// 内容文本 +@property (nonatomic, strong) UILabel *descLabel; +// 保存按钮 +@property (nonatomic, strong) UIButton *saveButton; +// 底部关闭按钮(圆形 X) +@property (nonatomic, strong) UIButton *closeButton; + +@end + +@implementation HomeRankDetailPopView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.backgroundColor = UIColor.clearColor; // 由 LSTPopView 提供半透明背景 + [self buildUI]; + [self makeConstraints]; + } + return self; +} + +#pragma mark - Public + +- (void)configWithAvatar:(UIImage *)avatar + title:(NSString *)title + download:(NSString *)download + desc:(NSString *)desc { + self.avatarView.image = avatar ?: [self placeholderAvatar]; + self.titleLabel.text = title ?: @""; + self.downloadLabel.text = download ?: @""; + self.descLabel.text = desc ?: @""; +} + +#pragma mark - Build UI + +- (void)buildUI { + // 添加顺序:先卡片,再头像(悬浮于卡片上方),最后底部关闭 + [self addSubview:self.cardView]; + [self addSubview:self.avatarView]; + [self addSubview:self.closeButton]; + + [self.cardView addSubview:self.titleLabel]; + [self.cardView addSubview:self.downloadLabel]; + [self.cardView addSubview:self.bubbleView]; + [self.bubbleView addSubview:self.descLabel]; + [self.cardView addSubview:self.saveButton]; +} + +- (void)makeConstraints { + // 说明:将卡片上下各预留出 48 的间距,顶部用于头像悬浮展示,底部用于放置关闭按钮 + [self.cardView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self); + make.top.equalTo(self).offset(KBFit(56)); + make.height.mas_equalTo(KBFit(358)); +// make.bottom.equalTo(self).offset(-72); + }]; + + [self.avatarView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.cardView); + make.centerY.equalTo(self.cardView.mas_top); // 一半悬浮在卡片外 + make.width.height.mas_equalTo(112); + }]; + + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.avatarView.mas_bottom).offset(KBFit(13)); + make.centerX.equalTo(self.cardView); + make.height.mas_equalTo(KBFit(23)); + }]; + + [self.downloadLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.titleLabel.mas_bottom).offset(KBFit(7)); + make.centerX.equalTo(self.cardView); + make.height.mas_equalTo(KBFit(23)); + }]; + + [self.bubbleView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.downloadLabel.mas_bottom).offset(KBFit(16)); + make.left.equalTo(self.cardView).offset(20); + make.right.equalTo(self.cardView).offset(-20); + make.height.mas_equalTo(KBFit(125)); + }]; + + [self.descLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.bubbleView).insets(UIEdgeInsetsMake(12, 12, 12, 12)); + }]; + + [self.saveButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.cardView).offset(20); + make.right.equalTo(self.cardView).offset(-20); + make.bottom.equalTo(self.cardView).offset(-KBFit(26)); + make.height.mas_equalTo(KBFit(48)); + }]; + + [self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.cardView.mas_bottom).offset(16); + make.centerX.equalTo(self.cardView); + make.width.height.mas_equalTo(36); + }]; +} + +#pragma mark - Actions + +- (void)onTapSave { + if (self.saveHandler) self.saveHandler(); +} + +- (void)onTapClose { + if (self.closeHandler) self.closeHandler(); +} + +#pragma mark - Helpers + +- (UIImage *)placeholderAvatar { + // 简单生成圆形纯色头像占位 + CGSize size = CGSizeMake(96, 96); + UIGraphicsBeginImageContextWithOptions(size, NO, 0); + CGContextRef ctx = UIGraphicsGetCurrentContext(); + [[UIColor colorWithRed:0.93 green:0.96 blue:0.99 alpha:1.0] setFill]; + CGContextFillEllipseInRect(ctx, CGRectMake(0, 0, size.width, size.height)); + UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return img; +} + +#pragma mark - Lazy UI + +- (UIView *)cardView { + if (!_cardView) { + _cardView = [UIView new]; + _cardView.backgroundColor = UIColor.whiteColor; + _cardView.layer.cornerRadius = 22.0; + _cardView.layer.masksToBounds = YES; + } + return _cardView; +} + +- (UIImageView *)avatarView { + if (!_avatarView) { + _avatarView = [[UIImageView alloc] init]; + _avatarView.contentMode = UIViewContentModeScaleAspectFill; + _avatarView.layer.cornerRadius = 56.0; + _avatarView.layer.masksToBounds = YES; + // 外环 + _avatarView.layer.borderColor = UIColor.whiteColor.CGColor; + _avatarView.layer.borderWidth = 4.0; + _avatarView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0]; + } + return _avatarView; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [UILabel new]; + _titleLabel.textColor = [UIColor colorWithHex:KBBlackValue]; + _titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + _titleLabel.text = @"High EQ"; // 默认文案 + } + return _titleLabel; +} + +- (UILabel *)downloadLabel { + if (!_downloadLabel) { + _downloadLabel = [UILabel new]; + _downloadLabel.textColor = [UIColor colorWithHex:KBColorValue]; + _downloadLabel.backgroundColor = [UIColor colorWithHex:0xEDFFFD]; + _downloadLabel.font = [UIFont systemFontOfSize:13 weight:UIFontWeightMedium]; + _downloadLabel.textAlignment = NSTextAlignmentCenter; + _downloadLabel.text = @"Download: 1 Million"; + } + return _downloadLabel; +} + +- (UIView *)bubbleView { + if (!_bubbleView) { + _bubbleView = [UIView new]; + _bubbleView.backgroundColor = [UIColor colorWithHex:0xF8F8F8]; + _bubbleView.layer.cornerRadius = 9.0; + _bubbleView.layer.masksToBounds = YES; + } + return _bubbleView; +} + +- (UILabel *)descLabel { + if (!_descLabel) { + _descLabel = [UILabel new]; + _descLabel.textColor = [UIColor colorWithHex:KBBlackValue]; + _descLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightSemibold]; + _descLabel.numberOfLines = 0; + _descLabel.text = @"Be Neither Too Close\nNor Too Distant"; + } + return _descLabel; +} + +- (UIButton *)saveButton { + if (!_saveButton) { + _saveButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_saveButton setTitle:@"Save" forState:UIControlStateNormal]; + [_saveButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal]; + _saveButton.titleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightSemibold]; + _saveButton.backgroundColor = [UIColor colorWithRed:0.02 green:0.75 blue:0.67 alpha:1.0]; + _saveButton.layer.cornerRadius = 24.0; + _saveButton.layer.masksToBounds = YES; + [_saveButton addTarget:self action:@selector(onTapSave) forControlEvents:UIControlEventTouchUpInside]; + } + return _saveButton; +} + +- (UIButton *)closeButton { + if (!_closeButton) { + _closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_closeButton setImage:[UIImage imageNamed:@"white_close_icon"] forState:UIControlStateNormal]; + [_closeButton addTarget:self action:@selector(onTapClose) forControlEvents:UIControlEventTouchUpInside]; + } + return _closeButton; +} + +@end + diff --git a/keyBoard/Class/Home/VC/HomeRankContentVC.m b/keyBoard/Class/Home/VC/HomeRankContentVC.m index 2f6687e..6ae6924 100644 --- a/keyBoard/Class/Home/VC/HomeRankContentVC.m +++ b/keyBoard/Class/Home/VC/HomeRankContentVC.m @@ -7,6 +7,8 @@ @import UIKit; #import "HomeRankContentVC.h" +#import "HomeRankDetailPopView.h" // 自定义弹窗内容视图 +#import "LSTPopView.h" // LSTPopView 弹窗框架 // 自定义卡片 Cell #import "HomeRankCardCell.h" @@ -92,16 +94,44 @@ #pragma mark - UICollectionViewDelegateFlowLayout - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { - CGFloat totalHInset = 16 + 16; // section i/l/r - CGFloat spacing = 16; // interitem spacing - CGFloat w = collectionView.bounds.size.width - totalHInset; // not including section insets yet - // Two columns → each width = (width - spacing - lr insets)/2 + CGFloat totalHInset = 16 + 16; + CGFloat spacing = 16; + CGFloat w = collectionView.bounds.size.width - totalHInset; CGFloat cellWidth = (w - spacing) / 2.0; // 固定高度,接近示意图比例 CGFloat cellHeight = 234.0; return CGSizeMake(floor(cellWidth), cellHeight); } +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ + // 点击卡片 -> 展示弹窗 + NSDictionary *d = self.dataSource[indexPath.item]; + + // 自定义内容视图(尺寸可按需调节) + CGFloat width = MIN(KB_SCREEN_WIDTH - 76, 420); + HomeRankDetailPopView *content = [[HomeRankDetailPopView alloc] initWithFrame:CGRectMake(0, 0, width, 460)]; + NSString *title = d[@"title"] ?: @"High EQ"; + NSString *people = d[@"people"] ?: @"Download: 1 Million"; + NSString *desc = @"Be Neither Too Close\nNor Too Distant"; // 示例文案 + [content configWithAvatar:nil title:title download:people desc:desc]; + + // 创建并弹出 + LSTPopView *pop = [LSTPopView initWithCustomView:content + parentView:nil + popStyle:LSTPopStyleScale + dismissStyle:LSTDismissStyleScale]; + pop.hemStyle = LSTHemStyleCenter; // 居中 + pop.bgColor = [[UIColor blackColor] colorWithAlphaComponent:0.4]; + pop.isClickBgDismiss = YES; // 点击背景关闭 + pop.cornerRadius = 0; // 自定义 view 自处理圆角 + + __weak typeof(pop) weakPop = pop; + content.saveHandler = ^{ [weakPop dismiss]; }; + content.closeHandler = ^{ [weakPop dismiss]; }; + + [pop pop]; +} + #pragma mark - JXCategoryListContentViewDelegate - (UIView *)listView { diff --git a/keyBoard/KeyBoardPrefixHeader.pch b/keyBoard/KeyBoardPrefixHeader.pch index c6406a1..a9d78d5 100644 --- a/keyBoard/KeyBoardPrefixHeader.pch +++ b/keyBoard/KeyBoardPrefixHeader.pch @@ -57,8 +57,10 @@ #define KB_TABBAR_BASE_HEIGHT 49.0 #define COLOR_WITH_RGB(R,G,B,A) [UIColor colorWithRed:R green:G blue:B alpha:A] - +/// 主题色 绿色 #define KBColorValue 0x02BEAC +/// 通用黑色 +#define KBBlackValue 0x1B1F1A // 当前 KeyWindow(iOS 13 场景化兼容) static inline UIWindow *KB_KeyWindow(void) {