From e34288ae56225247ed82967252c525b0378ab381 Mon Sep 17 00:00:00 2001 From: CodeST <694468528@qq.com> Date: Tue, 11 Nov 2025 15:13:43 +0800 Subject: [PATCH] fix ui --- .../myperson_edit_icon.imageset/Contents.json | 22 +++ .../myperson_edit_icon@2x.png | Bin 0 -> 1202 bytes .../myperson_edit_icon@3x.png | Bin 0 -> 2123 bytes keyBoard/Class/Me/V/KBPersonInfoItemCell.m | 34 +--- keyBoard/Class/Me/VC/KBPersonInfoVC.m | 161 ++++++++++++------ keyBoard/Info.plist | 6 + 6 files changed, 145 insertions(+), 78 deletions(-) create mode 100644 keyBoard/Assets.xcassets/My/myperson_edit_icon.imageset/Contents.json create mode 100644 keyBoard/Assets.xcassets/My/myperson_edit_icon.imageset/myperson_edit_icon@2x.png create mode 100644 keyBoard/Assets.xcassets/My/myperson_edit_icon.imageset/myperson_edit_icon@3x.png diff --git a/keyBoard/Assets.xcassets/My/myperson_edit_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/My/myperson_edit_icon.imageset/Contents.json new file mode 100644 index 0000000..727d2c7 --- /dev/null +++ b/keyBoard/Assets.xcassets/My/myperson_edit_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "myperson_edit_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "myperson_edit_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/My/myperson_edit_icon.imageset/myperson_edit_icon@2x.png b/keyBoard/Assets.xcassets/My/myperson_edit_icon.imageset/myperson_edit_icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1a3ead9cf867e569739c45a0409924219ec3f16a GIT binary patch literal 1202 zcmV;j1Wo&iP)LjNDe+B$xn_N zNuM-=w^XNFMAivpx#kfDbJ3dS-NX>f9vm9l4sz&3v8%YD#9*h`sZnEPpIE!G7@>Eb zJ;vZ8azMGf^WL$)p@D%KUHZL7gK>`uW!h< zxZfL=U5D1%Yu()M!_`&~oX;4-^kV|?J=!#ryyG6cf6HBXuSk4;TRZBbRpdr*V>1rl zxdrdGu6M_NAFg)#{NtQ=4GC;72Y%79d?nV_F2mW2Gx*^5(}D5QsUPrnYTh-oyLlZ{ z4ErX}_)#y^B_hvrVEB8(wsJuVPMdU(OuURh$>;y z&kS2vM5_@M1MWkP14GcHt0Z-Spdyn&W{R}tP3wuQGkMhzg{{{&f*Y87CigLgpvZ$7 z3;R!AwZy{Rbt{mDMY+t-i&4Ib67}<7FP<93`eTO{HgFywY{6o}h{$NzzAQdvEyid5 z%?_{ln_i4#arBCr%0xgfx~U@v%fwd(n#e(ej)%vs$TvZ37o9X_HSTX%g*VsU9xB@F zW0-RskRwRL^`KsKg`oS|*%Jgl^4Fi3n4Q7uYiiNk)DkLIFR8)V+5eE3J{Kgh;K4Nn z#180@JK@*y$J{J7jwJEa*fBga_HC$mTJf8|JB;)5bAI${#;SJg009|8@i-66P8R%v zgahX$@Zsbyp@KcUAwOQ$^|0=QdSIS0#H?c*H+LUXPgHu?hm5wXbIFhnohfIB1x7Tz zDi^gJ)yx%JWC&edGd4B>;Bzu8o33*B>Ai6A#Mpjux3 zd_zPi&`vpT|hOL;3Tr!iEUb$LHL;^;yT-2XuM$Sh9HeK@M_})BBimS^W)V zQF;Qb#M&IO+ugTmwqD{ldmJ&^8*9rwO@8gg4Y8B&i1@bsHvZ@)$3|N8NALwL_v`<_ z$Mw#qHBU2`v!;1JF~qV5@kjP&-!nQFc>NCm0RR6&@x%`R000I_L_t&o0Mlg{NkN1a QzW@LL07*qoM6N<$f>qvBqyPW_ literal 0 HcmV?d00001 diff --git a/keyBoard/Assets.xcassets/My/myperson_edit_icon.imageset/myperson_edit_icon@3x.png b/keyBoard/Assets.xcassets/My/myperson_edit_icon.imageset/myperson_edit_icon@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..87d2abdb04a1804c1cc54bc2420fd7f237d8378e GIT binary patch literal 2123 zcmV-R2(h>uDXQBc&h3YJh>Y)h#_=bq#5JEbt4&d__OGj*7J-^{t^ ze2?Gno^#LRjz+FNyI+Z7^O_i5TQ$Xdqh_wIt$9dosM)AC)_kcq*0kvjFZfPbmO8~Y zu@PJGalR5GM|cKC%vvRYyxJG8(0e=Y^%8hdMSeckl1w0R&=(Gs9il&Z>m|WeXJ*jr0F?k8W%DC%b$p9Tc@tMF~cSm6%gO_9a&4{fb6HD$3tN7s0p` z-I#k}?M;jep;C4sATv-ey8^zj6%I48Cxh%o%qxxlQ2~EQHaHo|f?2R9V?9ocdp~P& zD;onZzNKCSSH~*x#KiNkV$#%5x@^KZ7#;1KYT8dmV)3|%m{=k^E20S|#SS|;^q6-O zvzFWL$aSm?yiF2PD<)N8*@VfMM{@IG2h zac5&;#hFqaMk_VQfn2~(H?g}v?6TUwjZWvv^2cb|DKM)D>d;Z53h=pb(VVmrQxcM84} zYv0ykR=ALpMq}ql1y$A8CcibQ!_SAs*0yFW*tHG24!38W+;Jf%jn1wzYpom>vksPx zWAgCR?D==tgV%rl;ebd94#$O@wC6>txbF&ooR=tBsPvS~elq;ZiiR*X@Gg65$(K7E zDVZhDE*XldVZ#yCZVCvOMS*iqq)J;4Q^R>?Z!M&HW=g@=LsQ?yqrK`Dj-c_DeWvKKqlyI%aF%YxuFRwzM9=^}9bhMoQwIH*`2Aa&aza zZ~k_~X;Kwhg_CCdP}6+qEOd~bN*#Xh936h2cC^vrxJ0>7%QGh`Gw<=15G952S^=X% zxP&$pQvD6T&_Vlg5KeqQV@vz78&GqQ;WwZJ>71=C)#>VUQOCQ6t74T%p8YZnzg*-? zjiI4bM`~p*u4O8}uHt8I%1$@?j{RM6{&l7>l8 zzb7!BZbNc#TtG}xqu7D4kFZ!z4J5KQUAp~k+{BabQ+(U>bYlZ@qxHD0VJH5?*d5{4 zzj`Aa$VCWr_n4HbXCLCtx|zkmuZJYDyh2;>**09gt1c%hu^!v|RoF$n(_tqE;&*bK z7%%;f_{$b}mBo`v1hZgI2HlGoE}3)CTJ-=d_9hz@beUKkW@1mq*_)WOH2Ygf><$*= z)IyiI!z!3lkoF}ud$wY)L%I!*Rm?`B2L?ZN~h#B7IVx2{|OLFkbuF6NhFzhelv5kJsiJADa>b8;O!S} zvz2==I2m$3FKf0ggWx{gv#*S?qVvvL~=+j**Ijd z%~&0tSWhVK%gjZy?lK;Juaun+tsYfS@3A@jYX% #import "KBPersonInfoItemCell.h" +#import -@interface KBPersonInfoVC () +@interface KBPersonInfoVC () // 列表 @property (nonatomic, strong) BaseTableView *tableView; // 懒加载 @@ -25,13 +26,13 @@ @property (nonatomic, strong) UIButton *editBadge; // 头像右下角的小铅笔 @property (nonatomic, strong) UILabel *modifyLabel; // “Modify” 文案 -// 底部退出(表尾) -@property (nonatomic, strong) UIView *footerView; -@property (nonatomic, strong) UIView *logoutBg; +// 底部退出按钮(固定在屏幕底部) @property (nonatomic, strong) UIButton *logoutBtn; // 数据 @property (nonatomic, copy) NSArray *items; // {title,value,arrow,copy} +// 压缩后的头像 JPEG 数据(可用于上传) +@property (nonatomic, strong) NSData *avatarJPEGData; @end @@ -56,9 +57,22 @@ make.top.equalTo(self.view).offset(KB_NAV_TOTAL_HEIGHT + 10); }]; - // 表头 & 表尾 + // 表头 self.tableView.tableHeaderView = self.headerView; - self.tableView.tableFooterView = self.footerView; + + // 底部退出按钮固定在屏幕底部 + [self.view addSubview:self.logoutBtn]; + [self.logoutBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.view).offset(16); + make.right.equalTo(self.view).offset(-16); + make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom).offset(-12); + make.height.mas_equalTo(56); + }]; + + // 列表底部腾出空间,避免被按钮挡住 + UIEdgeInsets inset = self.tableView.contentInset; + inset.bottom = 56 + 24; // 按钮高度 + 额外间距 + self.tableView.contentInset = inset; } #pragma mark - UITableView @@ -101,9 +115,7 @@ #pragma mark - Actions -- (void)onTapAvatarEdit { - // 示例:更换头像 -} +- (void)onTapAvatarEdit { [self presentImagePicker]; } - (void)onTapLogout { // 示例:退出登录 @@ -141,14 +153,18 @@ }]; [self.editBadge mas_makeConstraints:^(MASConstraintMaker *make) { make.width.height.mas_equalTo(24); - make.centerX.equalTo(self.avatarView.mas_right).offset(-8); - make.centerY.equalTo(self.avatarView.mas_bottom).offset(-8); + make.centerX.equalTo(self.avatarView.mas_right).offset(-15); + make.centerY.equalTo(self.avatarView.mas_bottom).offset(-15); }]; [self.modifyLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.avatarView.mas_bottom).offset(10); make.centerX.equalTo(hv); }]; + // 头像可点击:弹系统相册 + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapAvatarEdit)]; + [self.avatarView addGestureRecognizer:tap]; + _headerView = hv; } return _headerView; @@ -177,14 +193,9 @@ - (UIButton *)editBadge { if (!_editBadge) { _editBadge = [UIButton buttonWithType:UIButtonTypeCustom]; - _editBadge.backgroundColor = [UIColor colorWithRed:0.02 green:0.75 blue:0.67 alpha:1.0]; _editBadge.layer.cornerRadius = 12; _editBadge.layer.masksToBounds = YES; - UIImage *img = nil; - if (@available(iOS 13.0, *)) img = [UIImage systemImageNamed:@"pencil"]; // 铅笔图标 + UIImage *img = [UIImage imageNamed:@"myperson_edit_icon"]; [_editBadge setImage:img forState:UIControlStateNormal]; - [_editBadge setTitle:(img ? @"" : @"✎") forState:UIControlStateNormal]; - _editBadge.titleLabel.font = [UIFont systemFontOfSize:12 weight:UIFontWeightBold]; - [_editBadge setTitleColor:UIColor.whiteColor forState:UIControlStateNormal]; [_editBadge addTarget:self action:@selector(onTapAvatarEdit) forControlEvents:UIControlEventTouchUpInside]; } return _editBadge; @@ -194,54 +205,98 @@ if (!_modifyLabel) { _modifyLabel = [UILabel new]; _modifyLabel.text = @"Modify"; - _modifyLabel.textColor = [UIColor blackColor]; + _modifyLabel.textColor = [UIColor colorWithHex:KBBlackValue]; _modifyLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightSemibold]; } return _modifyLabel; } -- (UIView *)footerView { - if (!_footerView) { - CGFloat w = UIScreen.mainScreen.bounds.size.width; - UIView *fv = [[UIView alloc] initWithFrame:CGRectMake(0, 0, w, 120)]; - fv.backgroundColor = UIColor.clearColor; - - [fv addSubview:self.logoutBg]; - [self.logoutBg mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.equalTo(fv).offset(16); - make.right.equalTo(fv).offset(-16); - make.top.equalTo(fv).offset(14); - make.height.mas_equalTo(56); - }]; - - [self.logoutBg addSubview:self.logoutBtn]; - [self.logoutBtn mas_makeConstraints:^(MASConstraintMaker *make) { - make.edges.equalTo(self.logoutBg); - }]; - - _footerView = fv; - } - return _footerView; -} - -- (UIView *)logoutBg { - if (!_logoutBg) { - _logoutBg = [UIView new]; - _logoutBg.backgroundColor = UIColor.whiteColor; - _logoutBg.layer.cornerRadius = 12; _logoutBg.layer.masksToBounds = YES; - } - return _logoutBg; -} - - (UIButton *)logoutBtn { if (!_logoutBtn) { _logoutBtn = [UIButton buttonWithType:UIButtonTypeSystem]; [_logoutBtn setTitle:@"Log Out" forState:UIControlStateNormal]; - [_logoutBtn setTitleColor:[UIColor colorWithRed:0.85 green:0.15 blue:0.11 alpha:1.0] forState:UIControlStateNormal]; - _logoutBtn.titleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightSemibold]; + [_logoutBtn setTitleColor:[UIColor colorWithHex:0xFF0000] forState:UIControlStateNormal]; + _logoutBtn.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + _logoutBtn.backgroundColor = UIColor.whiteColor; + _logoutBtn.layer.cornerRadius = 12; _logoutBtn.layer.masksToBounds = YES; [_logoutBtn addTarget:self action:@selector(onTapLogout) forControlEvents:UIControlEventTouchUpInside]; } return _logoutBtn; } +#pragma mark - Image Picker + +- (void)presentImagePicker { + if (@available(iOS 14.0, *)) { + PHPickerConfiguration *config = [[PHPickerConfiguration alloc] init]; + config.selectionLimit = 1; // 只选一张 + config.filter = [PHPickerFilter imagesFilter]; + PHPickerViewController *picker = [[PHPickerViewController alloc] initWithConfiguration:config]; + picker.delegate = self; + [self presentViewController:picker animated:YES completion:nil]; + } else { + UIImagePickerController *picker = [[UIImagePickerController alloc] init]; + picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; + picker.delegate = self; + [self presentViewController:picker animated:YES completion:nil]; + } +} + +#pragma mark - PHPickerViewControllerDelegate + +- (void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray *)results API_AVAILABLE(ios(14.0)) { + [picker dismissViewControllerAnimated:YES completion:nil]; + PHPickerResult *first = results.firstObject; if (!first) return; + NSItemProvider *p = first.itemProvider; + if ([p canLoadObjectOfClass:UIImage.class]) { + __weak typeof(self) weakSelf = self; + [p loadObjectOfClass:UIImage.class completionHandler:^(__kindof id _Nullable object, NSError * _Nullable error) { + UIImage *img = ([object isKindOfClass:UIImage.class] ? (UIImage *)object : nil); + if (!img) return; + dispatch_async(dispatch_get_main_queue(), ^{ + UIImage *compressed = [weakSelf kb_compressImage:img maxPixel:512 quality:0.85]; + weakSelf.avatarView.image = compressed; + weakSelf.avatarJPEGData = UIImageJPEGRepresentation(compressed, 0.85); + }); + }]; + } +} + +#pragma mark - UIImagePickerControllerDelegate + +- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { + UIImage *img = info[UIImagePickerControllerEditedImage] ?: info[UIImagePickerControllerOriginalImage]; + if (img) { + UIImage *compressed = [self kb_compressImage:img maxPixel:512 quality:0.85]; + self.avatarView.image = compressed; + self.avatarJPEGData = UIImageJPEGRepresentation(compressed, 0.85); + } + [picker dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { + [picker dismissViewControllerAnimated:YES completion:nil]; +} + +/// 压缩图片:最长边不超过 maxPixel,输出近似 quality 的 JPEG +- (UIImage *)kb_compressImage:(UIImage *)image maxPixel:(CGFloat)maxPixel quality:(CGFloat)quality { + if (!image) return nil; + maxPixel = MAX(64, maxPixel); + CGSize size = image.size; + CGFloat maxSide = MAX(size.width, size.height); + CGSize target = size; + if (maxSide > maxPixel) { + CGFloat scale = maxPixel / maxSide; + target = CGSizeMake(floor(size.width * scale), floor(size.height * scale)); + } + UIGraphicsBeginImageContextWithOptions(target, YES, 1.0); + [image drawInRect:CGRectMake(0, 0, target.width, target.height)]; + UIImage *scaled = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + NSData *jpeg = UIImageJPEGRepresentation(scaled ?: image, MIN(MAX(quality, 0.2), 0.95)); + UIImage *result = [UIImage imageWithData:jpeg] ?: scaled ?: image; + return result; +} + @end diff --git a/keyBoard/Info.plist b/keyBoard/Info.plist index c798311..94ec165 100644 --- a/keyBoard/Info.plist +++ b/keyBoard/Info.plist @@ -20,5 +20,11 @@ NSAllowsArbitraryLoads + + NSPhotoLibraryUsageDescription + 更换头像需要访问您的相册 + + NSPhotoLibraryAddUsageDescription + 保存图片需要写入您的相册