fix ui
This commit is contained in:
@@ -85,6 +85,7 @@
|
||||
049FB2232EC311F900FAB05D /* KBPersonInfoVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB2222EC311F900FAB05D /* KBPersonInfoVC.m */; };
|
||||
049FB2262EC3136D00FAB05D /* KBPersonInfoItemCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB2252EC3136D00FAB05D /* KBPersonInfoItemCell.m */; };
|
||||
049FB2292EC31BB000FAB05D /* KBChangeNicknamePopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB2282EC31BB000FAB05D /* KBChangeNicknamePopView.m */; };
|
||||
049FB22C2EC31F8800FAB05D /* KBGenderPickerPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB22B2EC31F8800FAB05D /* KBGenderPickerPopView.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 */; };
|
||||
@@ -296,6 +297,8 @@
|
||||
049FB2252EC3136D00FAB05D /* KBPersonInfoItemCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBPersonInfoItemCell.m; sourceTree = "<group>"; };
|
||||
049FB2272EC31BB000FAB05D /* KBChangeNicknamePopView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChangeNicknamePopView.h; sourceTree = "<group>"; };
|
||||
049FB2282EC31BB000FAB05D /* KBChangeNicknamePopView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChangeNicknamePopView.m; sourceTree = "<group>"; };
|
||||
049FB22A2EC31F8800FAB05D /* KBGenderPickerPopView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBGenderPickerPopView.h; sourceTree = "<group>"; };
|
||||
049FB22B2EC31F8800FAB05D /* KBGenderPickerPopView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBGenderPickerPopView.m; sourceTree = "<group>"; };
|
||||
049FB31B2EC21BCD00FAB05D /* KBMyKeyboardCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBMyKeyboardCell.h; sourceTree = "<group>"; };
|
||||
049FB31C2EC21BCD00FAB05D /* KBMyKeyboardCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBMyKeyboardCell.m; sourceTree = "<group>"; };
|
||||
04A9A67D2EB9E1690023B8F4 /* KBResponderUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBResponderUtils.h; sourceTree = "<group>"; };
|
||||
@@ -890,6 +893,8 @@
|
||||
049FB2252EC3136D00FAB05D /* KBPersonInfoItemCell.m */,
|
||||
049FB2272EC31BB000FAB05D /* KBChangeNicknamePopView.h */,
|
||||
049FB2282EC31BB000FAB05D /* KBChangeNicknamePopView.m */,
|
||||
049FB22A2EC31F8800FAB05D /* KBGenderPickerPopView.h */,
|
||||
049FB22B2EC31F8800FAB05D /* KBGenderPickerPopView.m */,
|
||||
);
|
||||
path = V;
|
||||
sourceTree = "<group>";
|
||||
@@ -1426,6 +1431,7 @@
|
||||
048908E32EBF821700FABA60 /* KBSkinDetailVC.m in Sources */,
|
||||
0477BDF32EBB7B850055D639 /* KBDirectionIndicatorView.m in Sources */,
|
||||
049FB21A2EC20A9E00FAB05D /* KBMyKeyBoardVC.m in Sources */,
|
||||
049FB22C2EC31F8800FAB05D /* KBGenderPickerPopView.m in Sources */,
|
||||
048908D22EBF611D00FABA60 /* KBHistoryMoreCell.m in Sources */,
|
||||
04FC95D82EB1EA16007BD342 /* BaseCell.m in Sources */,
|
||||
0477BDF72EBC63A80055D639 /* KBTestVC.m in Sources */,
|
||||
|
||||
33
keyBoard/Class/Me/V/KBGenderPickerPopView.h
Normal file
33
keyBoard/Class/Me/V/KBGenderPickerPopView.h
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// KBGenderPickerPopView.h
|
||||
// keyBoard
|
||||
//
|
||||
// Created by Codex on 2025/11/11.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// 性别选择弹窗自定义视图(给 LSTPopView 使用)
|
||||
/// - 使用 UIPickerView 实现上下滑动
|
||||
/// - Masonry 约束、懒加载、中文注释
|
||||
@interface KBGenderPickerPopView : UIView
|
||||
|
||||
/// 数据源(元素为 NSDictionary,包含 key: id, name)
|
||||
@property (nonatomic, copy) NSArray<NSDictionary *> *items;
|
||||
/// 预选中的 id(可为空)
|
||||
@property (nonatomic, copy, nullable) NSString *selectedId;
|
||||
|
||||
/// 保存回调,返回选中的字典
|
||||
@property (nonatomic, copy, nullable) void (^saveHandler)(NSDictionary *selected);
|
||||
/// 关闭回调
|
||||
@property (nonatomic, copy, nullable) void (^closeHandler)(void);
|
||||
|
||||
/// 将选择器滚动到 selectedId 对应的行
|
||||
- (void)syncSelection;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
233
keyBoard/Class/Me/V/KBGenderPickerPopView.m
Normal file
233
keyBoard/Class/Me/V/KBGenderPickerPopView.m
Normal file
@@ -0,0 +1,233 @@
|
||||
//
|
||||
// KBGenderPickerPopView.m
|
||||
// keyBoard
|
||||
//
|
||||
// Created by Codex on 2025/11/11.
|
||||
//
|
||||
|
||||
@import UIKit;
|
||||
#import "KBGenderPickerPopView.h"
|
||||
#import <Masonry/Masonry.h>
|
||||
|
||||
@interface KBGenderPickerPopView () <UIPickerViewDelegate, UIPickerViewDataSource>
|
||||
|
||||
// 白底圆角卡片容器
|
||||
@property (nonatomic, strong) UIView *cardView;
|
||||
// 标题
|
||||
@property (nonatomic, strong) UILabel *titleLabel;
|
||||
// 右上角关闭(下拉箭头)
|
||||
@property (nonatomic, strong) UIButton *closeButton;
|
||||
// 选择器
|
||||
@property (nonatomic, strong) UIPickerView *picker;
|
||||
// 选中区域的上/下分隔线(模拟系统选择线)
|
||||
@property (nonatomic, strong) UIView *lineTop;
|
||||
@property (nonatomic, strong) UIView *lineBottom;
|
||||
// 保存按钮
|
||||
@property (nonatomic, strong) UIButton *saveButton;
|
||||
|
||||
@end
|
||||
|
||||
@implementation KBGenderPickerPopView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
self.backgroundColor = UIColor.clearColor;
|
||||
// 默认三项
|
||||
_items = @[
|
||||
@{ @"id": @"1", @"name": @"Male" },
|
||||
@{ @"id": @"2", @"name": @"Female" },
|
||||
@{ @"id": @"3", @"name": @"The Third Gender" },
|
||||
];
|
||||
[self buildUI];
|
||||
[self makeConstraints];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
- (void)setItems:(NSArray<NSDictionary *> *)items {
|
||||
_items = [items copy];
|
||||
[self.picker reloadAllComponents];
|
||||
[self syncSelection];
|
||||
}
|
||||
|
||||
- (void)setSelectedId:(NSString *)selectedId {
|
||||
_selectedId = [selectedId copy];
|
||||
[self syncSelection];
|
||||
}
|
||||
|
||||
- (void)syncSelection {
|
||||
// 找到选中 id 对应的行(避免 __block,可直接用 indexOfObjectPassingTest)
|
||||
NSInteger row = 0;
|
||||
if (self.selectedId.length > 0) {
|
||||
NSUInteger idx = [self.items indexOfObjectPassingTest:^BOOL(NSDictionary *obj, NSUInteger idx, BOOL *stop) {
|
||||
return [[obj objectForKey:@"id"] ?: @"" isEqualToString:self.selectedId];
|
||||
}];
|
||||
if (idx != NSNotFound) row = (NSInteger)idx;
|
||||
}
|
||||
if (row < (NSInteger)self.items.count) {
|
||||
[self.picker selectRow:row inComponent:0 animated:NO];
|
||||
}
|
||||
[self.picker reloadAllComponents];
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (void)onTapClose { if (self.closeHandler) self.closeHandler(); }
|
||||
|
||||
- (void)onTapSave {
|
||||
NSInteger row = [self.picker selectedRowInComponent:0];
|
||||
if (row >= 0 && row < (NSInteger)self.items.count) {
|
||||
NSDictionary *sel = self.items[row];
|
||||
if (self.saveHandler) self.saveHandler(sel);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UI
|
||||
|
||||
- (void)buildUI {
|
||||
[self addSubview:self.cardView];
|
||||
[self.cardView addSubview:self.titleLabel];
|
||||
[self.cardView addSubview:self.closeButton];
|
||||
[self.cardView addSubview:self.picker];
|
||||
[self.cardView addSubview:self.lineTop];
|
||||
[self.cardView addSubview:self.lineBottom];
|
||||
[self.cardView addSubview:self.saveButton];
|
||||
}
|
||||
|
||||
- (void)makeConstraints {
|
||||
[self.cardView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self); }];
|
||||
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.cardView).offset(20);
|
||||
make.top.equalTo(self.cardView).offset(18);
|
||||
}];
|
||||
[self.titleLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
|
||||
[self.titleLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
|
||||
[self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerY.equalTo(self.titleLabel);
|
||||
make.right.equalTo(self.cardView).offset(-16);
|
||||
make.width.height.mas_equalTo(36);
|
||||
}];
|
||||
[self.picker mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.cardView).offset(10);
|
||||
make.right.equalTo(self.cardView).offset(-10);
|
||||
make.top.equalTo(self.titleLabel.mas_bottom).offset(6);
|
||||
make.bottom.equalTo(self.saveButton.mas_top).offset(0);
|
||||
}];
|
||||
// 选中区域分隔线放在 picker 上方
|
||||
CGFloat rowH = 48;
|
||||
[self.lineTop mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.right.equalTo(self.picker);
|
||||
make.centerY.equalTo(self.picker).offset(-rowH/2.0);
|
||||
make.height.mas_equalTo(1);
|
||||
}];
|
||||
[self.lineBottom mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.right.equalTo(self.picker);
|
||||
make.centerY.equalTo(self.picker).offset(rowH/2.0);
|
||||
make.height.mas_equalTo(1);
|
||||
}];
|
||||
[self.saveButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.cardView).offset(16);
|
||||
make.right.equalTo(self.cardView).offset(-16);
|
||||
make.bottom.equalTo(self.cardView).offset(-18);
|
||||
make.height.mas_equalTo(46);
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Picker
|
||||
|
||||
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { return 1; }
|
||||
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { return self.items.count; }
|
||||
|
||||
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component { return 48.0; }
|
||||
|
||||
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
|
||||
UILabel *label = (UILabel *)view;
|
||||
if (![label isKindOfClass:UILabel.class]) {
|
||||
label = [[UILabel alloc] init];
|
||||
label.textAlignment = NSTextAlignmentCenter;
|
||||
label.font = [UIFont systemFontOfSize:20 weight:UIFontWeightSemibold];
|
||||
}
|
||||
NSString *name = self.items[row][@"name"] ?: @"";
|
||||
label.text = name;
|
||||
BOOL selected = (row == [pickerView selectedRowInComponent:0]);
|
||||
label.textColor = selected ? [UIColor colorWithRed:0.02 green:0.75 blue:0.67 alpha:1.0]
|
||||
: [UIColor colorWithWhite:0.65 alpha:1.0];
|
||||
return label;
|
||||
}
|
||||
|
||||
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
|
||||
// 选中变化后刷新颜色
|
||||
[pickerView reloadAllComponents];
|
||||
}
|
||||
|
||||
#pragma mark - Lazy UI
|
||||
|
||||
- (UIView *)cardView {
|
||||
if (!_cardView) {
|
||||
_cardView = [UIView new];
|
||||
_cardView.backgroundColor = UIColor.whiteColor;
|
||||
_cardView.layer.cornerRadius = 18.0; _cardView.layer.masksToBounds = YES;
|
||||
}
|
||||
return _cardView;
|
||||
}
|
||||
|
||||
- (UILabel *)titleLabel {
|
||||
if (!_titleLabel) {
|
||||
_titleLabel = [UILabel new];
|
||||
_titleLabel.text = @"Modify Gender";
|
||||
_titleLabel.textColor = [UIColor blackColor];
|
||||
_titleLabel.font = [UIFont systemFontOfSize:22 weight:UIFontWeightBold];
|
||||
}
|
||||
return _titleLabel;
|
||||
}
|
||||
|
||||
- (UIButton *)closeButton {
|
||||
if (!_closeButton) {
|
||||
_closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
_closeButton.backgroundColor = [UIColor colorWithWhite:1 alpha:0.95];
|
||||
_closeButton.layer.cornerRadius = 18.0; _closeButton.layer.masksToBounds = YES;
|
||||
UIImage *img = nil; if (@available(iOS 13.0, *)) img = [UIImage systemImageNamed:@"chevron.down"];
|
||||
[_closeButton setImage:img forState:UIControlStateNormal];
|
||||
if (!img) { [_closeButton setTitle:@"∨" forState:UIControlStateNormal]; }
|
||||
[_closeButton setTitleColor:[UIColor colorWithWhite:0.3 alpha:1] forState:UIControlStateNormal];
|
||||
_closeButton.tintColor = [UIColor colorWithWhite:0.3 alpha:1];
|
||||
[_closeButton addTarget:self action:@selector(onTapClose) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
return _closeButton;
|
||||
}
|
||||
|
||||
- (UIPickerView *)picker {
|
||||
if (!_picker) {
|
||||
_picker = [[UIPickerView alloc] init];
|
||||
_picker.dataSource = self; _picker.delegate = self;
|
||||
_picker.backgroundColor = UIColor.clearColor;
|
||||
}
|
||||
return _picker;
|
||||
}
|
||||
|
||||
- (UIView *)lineTop {
|
||||
if (!_lineTop) { _lineTop = [self makeLine]; }
|
||||
return _lineTop;
|
||||
}
|
||||
- (UIView *)lineBottom {
|
||||
if (!_lineBottom) { _lineBottom = [self makeLine]; }
|
||||
return _lineBottom;
|
||||
}
|
||||
- (UIView *)makeLine { UIView *v = [UIView new]; v.backgroundColor = [UIColor colorWithWhite:0.88 alpha:1.0]; return v; }
|
||||
|
||||
- (UIButton *)saveButton {
|
||||
if (!_saveButton) {
|
||||
_saveButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
[_saveButton setTitle:@"Save" forState:UIControlStateNormal];
|
||||
[_saveButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
|
||||
_saveButton.titleLabel.font = [UIFont systemFontOfSize:20 weight:UIFontWeightSemibold];
|
||||
_saveButton.backgroundColor = [UIColor colorWithRed:0.02 green:0.75 blue:0.67 alpha:1.0];
|
||||
_saveButton.layer.cornerRadius = 23.0; _saveButton.layer.masksToBounds = YES;
|
||||
[_saveButton addTarget:self action:@selector(onTapSave) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
return _saveButton;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -16,6 +16,7 @@
|
||||
#import <PhotosUI/PhotosUI.h>
|
||||
#import "LSTPopView.h"
|
||||
#import "KBChangeNicknamePopView.h"
|
||||
#import "KBGenderPickerPopView.h"
|
||||
|
||||
@interface KBPersonInfoVC () <UITableViewDelegate, UITableViewDataSource, PHPickerViewControllerDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate>
|
||||
|
||||
@@ -107,10 +108,9 @@
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
// 示例:点击昵称/性别执行操作;用户 ID 行点击不处理(有复制按钮)
|
||||
if (indexPath.row == 0) {
|
||||
// 昵称编辑 -> 弹窗
|
||||
CGFloat width = MIN(KB_SCREEN_WIDTH - 48, 360);
|
||||
CGFloat width = KB_SCREEN_WIDTH;
|
||||
KBChangeNicknamePopView *content = [[KBChangeNicknamePopView alloc] initWithFrame:CGRectMake(0, 0, width, 230)];
|
||||
content.prefillNickname = self.items.firstObject[@"value"] ?: @"";
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
popStyle:LSTPopStyleSmoothFromBottom
|
||||
dismissStyle:LSTDismissStyleScale];
|
||||
pop.bgColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
|
||||
pop.hemStyle = LSTHemStyleCenter; // 居中
|
||||
pop.hemStyle = LSTHemStyleBottom; // 居中
|
||||
pop.isClickBgDismiss = YES; // 点击背景关闭
|
||||
pop.isAvoidKeyboard = YES; // 规避键盘
|
||||
pop.avoidKeyboardSpace = 10;
|
||||
@@ -139,9 +139,39 @@
|
||||
};
|
||||
|
||||
[pop pop];
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.15 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [content focusInput]; });
|
||||
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.15 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [content focusInput]; });
|
||||
} else if (indexPath.row == 1) {
|
||||
// TODO: 性别选择
|
||||
// 性别选择 -> 弹窗
|
||||
NSArray *genders = @[ @{@"id":@"1",@"name":@"Male"}, @{@"id":@"2",@"name":@"Female"}, @{@"id":@"3",@"name":@"The Third Gender"} ];
|
||||
CGFloat width = KB_SCREEN_WIDTH;
|
||||
KBGenderPickerPopView *content = [[KBGenderPickerPopView alloc] initWithFrame:CGRectMake(0, 0, width, 300)];
|
||||
content.items = genders;
|
||||
// 取当前展示值对应的 id(如果有的话)
|
||||
NSString *curName = self.items[1][@"value"];
|
||||
NSString *selId = nil;
|
||||
for (NSDictionary *d in genders) { if ([d[@"name"] isEqualToString:curName]) { selId = d[@"id"]; break; } }
|
||||
content.selectedId = selId;
|
||||
|
||||
LSTPopView *pop = [LSTPopView initWithCustomView:content
|
||||
parentView:nil
|
||||
popStyle:LSTPopStyleSmoothFromBottom
|
||||
dismissStyle:LSTDismissStyleSmoothToBottom];
|
||||
pop.bgColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
|
||||
pop.hemStyle = LSTHemStyleBottom;
|
||||
pop.isClickBgDismiss = YES;
|
||||
|
||||
__weak typeof(self) weakSelf = self; __weak typeof(pop) weakPop = pop;
|
||||
content.closeHandler = ^{ [weakPop dismiss]; };
|
||||
content.saveHandler = ^(NSDictionary *selected) {
|
||||
NSString *name = selected[@"name"] ?: @"";
|
||||
NSMutableArray *m = [weakSelf.items mutableCopy];
|
||||
NSMutableDictionary *d1 = [m[1] mutableCopy];
|
||||
d1[@"value"] = name; m[1] = d1; weakSelf.items = m;
|
||||
[weakSelf.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:1 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
|
||||
[weakPop dismiss];
|
||||
};
|
||||
|
||||
[pop pop];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user