fix ui
This commit is contained in:
22
keyBoard/Assets.xcassets/My/myperson_edit_icon.imageset/Contents.json
vendored
Normal file
22
keyBoard/Assets.xcassets/My/myperson_edit_icon.imageset/Contents.json
vendored
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
BIN
keyBoard/Assets.xcassets/My/myperson_edit_icon.imageset/myperson_edit_icon@2x.png
vendored
Normal file
BIN
keyBoard/Assets.xcassets/My/myperson_edit_icon.imageset/myperson_edit_icon@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
BIN
keyBoard/Assets.xcassets/My/myperson_edit_icon.imageset/myperson_edit_icon@3x.png
vendored
Normal file
BIN
keyBoard/Assets.xcassets/My/myperson_edit_icon.imageset/myperson_edit_icon@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
@@ -21,7 +21,7 @@
|
||||
// 复制按钮
|
||||
@property (nonatomic, strong) UIButton *copyBtn;
|
||||
// 分割线
|
||||
@property (nonatomic, strong) UIView *line;
|
||||
// 废弃分割线:按需求不显示底部分割线
|
||||
// 记录圆角位置,layoutSubviews 时更新 mask
|
||||
@property (nonatomic, assign) UIRectCorner cornerRecord;
|
||||
@end
|
||||
@@ -38,7 +38,6 @@
|
||||
[self.cardView addSubview:self.valueLabel];
|
||||
[self.cardView addSubview:self.arrowView];
|
||||
[self.cardView addSubview:self.copyBtn];
|
||||
[self.cardView addSubview:self.line];
|
||||
|
||||
[self.cardView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.contentView).offset(16);
|
||||
@@ -70,20 +69,15 @@
|
||||
make.right.equalTo(self.arrowView.mas_left).offset(-8);
|
||||
}];
|
||||
|
||||
[self.line mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.cardView).offset(16);
|
||||
make.right.equalTo(self.cardView).offset(-16);
|
||||
make.bottom.equalTo(self.cardView);
|
||||
make.height.mas_equalTo(0.5);
|
||||
}];
|
||||
// 不添加底部分割线
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
// 卡片圆角半径保持一致
|
||||
self.cardView.layer.cornerRadius = 12.0;
|
||||
// 根据位置设置圆角:顶部或底部为 12,中间为 0
|
||||
self.cardView.layer.cornerRadius = (self.cornerRecord != 0 ? 12.0 : 0.0);
|
||||
// 根据记录的 corner 重新生成 mask,保证尺寸变化后仍正确
|
||||
if (self.cornerRecord != 0 && !CGRectIsEmpty(self.cardView.bounds)) {
|
||||
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.cardView.bounds
|
||||
@@ -100,7 +94,6 @@
|
||||
- (void)prepareForReuse {
|
||||
[super prepareForReuse];
|
||||
self.arrowView.hidden = YES; self.copyBtn.hidden = YES;
|
||||
self.line.hidden = NO;
|
||||
}
|
||||
|
||||
- (void)configWithTitle:(NSString *)title
|
||||
@@ -126,15 +119,12 @@
|
||||
UIRectCorner corners = 0;
|
||||
if (isTop && isBottom) {
|
||||
corners = UIRectCornerAllCorners;
|
||||
self.line.hidden = YES;
|
||||
} else if (isTop) {
|
||||
corners = UIRectCornerTopLeft | UIRectCornerTopRight;
|
||||
self.line.hidden = NO;
|
||||
} else if (isBottom) {
|
||||
corners = UIRectCornerBottomLeft | UIRectCornerBottomRight;
|
||||
self.line.hidden = YES; // 底部不需要分割线
|
||||
} else {
|
||||
corners = 0; self.line.hidden = NO;
|
||||
corners = 0;
|
||||
}
|
||||
|
||||
// 使用遮罩实现指定圆角
|
||||
@@ -149,7 +139,7 @@
|
||||
if (!_cardView) {
|
||||
_cardView = [UIView new];
|
||||
_cardView.backgroundColor = UIColor.whiteColor;
|
||||
_cardView.layer.cornerRadius = 12.0;
|
||||
_cardView.layer.cornerRadius = 0.0; // 具体圆角在 layoutSubviews 中按位置设置
|
||||
_cardView.layer.masksToBounds = YES; // 配合圆角
|
||||
}
|
||||
return _cardView;
|
||||
@@ -158,7 +148,7 @@
|
||||
- (UILabel *)titleLabel {
|
||||
if (!_titleLabel) {
|
||||
_titleLabel = [UILabel new];
|
||||
_titleLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1.0];
|
||||
_titleLabel.textColor = [UIColor colorWithHex:KBBlackValue];
|
||||
_titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightRegular];
|
||||
}
|
||||
return _titleLabel;
|
||||
@@ -167,7 +157,7 @@
|
||||
- (UILabel *)valueLabel {
|
||||
if (!_valueLabel) {
|
||||
_valueLabel = [UILabel new];
|
||||
_valueLabel.textColor = [UIColor blackColor];
|
||||
_valueLabel.textColor = [UIColor colorWithHex:KBBlackValue];
|
||||
_valueLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold];
|
||||
_valueLabel.textAlignment = NSTextAlignmentRight;
|
||||
[_valueLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
|
||||
@@ -230,13 +220,7 @@
|
||||
return _copyBtn;
|
||||
}
|
||||
|
||||
- (UIView *)line {
|
||||
if (!_line) {
|
||||
_line = [UIView new];
|
||||
_line.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0];
|
||||
}
|
||||
return _line;
|
||||
}
|
||||
// 无分割线
|
||||
|
||||
#pragma mark - Event
|
||||
|
||||
|
||||
@@ -13,8 +13,9 @@
|
||||
#import "KBPersonInfoVC.h"
|
||||
#import <Masonry/Masonry.h>
|
||||
#import "KBPersonInfoItemCell.h"
|
||||
#import <PhotosUI/PhotosUI.h>
|
||||
|
||||
@interface KBPersonInfoVC () <UITableViewDelegate, UITableViewDataSource>
|
||||
@interface KBPersonInfoVC () <UITableViewDelegate, UITableViewDataSource, PHPickerViewControllerDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate>
|
||||
|
||||
// 列表
|
||||
@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<NSDictionary *> *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<PHPickerResult *> *)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<NSItemProviderReading> _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<UIImagePickerControllerInfoKey,id> *)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
|
||||
|
||||
@@ -20,5 +20,11 @@
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<!-- 相册权限:更换头像需要访问相册 -->
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>更换头像需要访问您的相册</string>
|
||||
<!-- 若未来需要保存图片到相册,可保留此项(当前仅选择不需要) -->
|
||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||
<string>保存图片需要写入您的相册</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
Reference in New Issue
Block a user