// // KBToolBar.m // CustomKeyboard // // Created by Mac on 2025/10/28. // #import "KBToolBar.h" #import "KBResponderUtils.h" // 查找 UIInputViewController,用于系统切换输入法 @interface KBToolBar () @property (nonatomic, strong) UIView *leftContainer; @property (nonatomic, strong) NSArray *leftButtonsInternal; @property (nonatomic, strong) UIButton *settingsButtonInternal; @property (nonatomic, strong) UIButton *globeButtonInternal; // 可选:系统“切换输入法”键 @end @implementation KBToolBar - (instancetype)initWithFrame:(CGRect)frame{ if (self = [super initWithFrame:frame]) { self.backgroundColor = [UIColor clearColor]; _leftButtonTitles = @[@"Item1", @"Item2", @"Item3", @"Item4"]; // 默认标题 [self setupUI]; } return self; } #pragma mark - Public - (NSArray *)leftButtons { return self.leftButtonsInternal; } - (UIButton *)settingsButton { return self.settingsButtonInternal; } - (void)setLeftButtonTitles:(NSArray *)leftButtonTitles { _leftButtonTitles = [leftButtonTitles copy]; // Update titles if buttons already exist [self.leftButtonsInternal enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if (idx < self.leftButtonTitles.count) { [obj setTitle:self.leftButtonTitles[idx] forState:UIControlStateNormal]; } }]; } #pragma mark - 视图搭建 - (void)setupUI { [self addSubview:self.leftContainer]; [self addSubview:self.settingsButtonInternal]; [self addSubview:self.globeButtonInternal]; // 右侧设置按钮 [self.settingsButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { make.right.equalTo(self.mas_right).offset(-12); make.centerY.equalTo(self.mas_centerY); make.width.height.mas_equalTo(32); }]; // 左侧地球键(按需显示) [self.globeButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.mas_left).offset(12); make.centerY.equalTo(self.mas_centerY); make.width.height.mas_equalTo(32); }]; // 左侧容器占用剩余空间 [self.leftContainer mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.globeButtonInternal.mas_right).offset(8); make.right.equalTo(self.settingsButtonInternal.mas_left).offset(-12); make.centerY.equalTo(self.mas_centerY); make.height.mas_equalTo(32); }]; // 在左侧容器中创建 4 个等宽按钮 NSMutableArray *buttons = [NSMutableArray arrayWithCapacity:4]; UIView *previous = nil; for (NSInteger i = 0; i < 4; i++) { UIButton *btn = [self buildActionButtonAtIndex:i]; [self.leftContainer addSubview:btn]; [buttons addObject:btn]; [btn mas_makeConstraints:^(MASConstraintMaker *make) { if (previous) { make.left.equalTo(previous.mas_right).offset(8); make.width.equalTo(previous); } else { make.left.equalTo(self.leftContainer.mas_left); } make.top.bottom.equalTo(self.leftContainer); }]; previous = btn; } // 最后一个按钮贴右侧 [previous mas_makeConstraints:^(MASConstraintMaker *make) { make.right.equalTo(self.leftContainer.mas_right); }]; self.leftButtonsInternal = buttons.copy; // 初始刷新地球键的可见性与事件绑定 [self kb_refreshGlobeVisibility]; } - (UIButton *)buildActionButtonAtIndex:(NSInteger)idx { UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem]; btn.layer.cornerRadius = 16; btn.layer.masksToBounds = YES; btn.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9]; btn.titleLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium]; NSString *title = (idx < self.leftButtonTitles.count) ? self.leftButtonTitles[idx] : [NSString stringWithFormat:@"Item%ld", (long)(idx+1)]; [btn setTitle:title forState:UIControlStateNormal]; [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; btn.tag = idx; [btn addTarget:self action:@selector(onLeftAction:) forControlEvents:UIControlEventTouchUpInside]; return btn; } #pragma mark - Actions - (void)onLeftAction:(UIButton *)sender { if ([self.delegate respondsToSelector:@selector(toolBar:didTapActionAtIndex:)]) { [self.delegate toolBar:self didTapActionAtIndex:sender.tag]; } } - (void)onSettings { if ([self.delegate respondsToSelector:@selector(toolBarDidTapSettings:)]) { [self.delegate toolBarDidTapSettings:self]; } } #pragma mark - Lazy - (UIView *)leftContainer { if (!_leftContainer) { _leftContainer = [[UIView alloc] init]; _leftContainer.backgroundColor = [UIColor clearColor]; } return _leftContainer; } - (UIButton *)settingsButtonInternal { if (!_settingsButtonInternal) { _settingsButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem]; _settingsButtonInternal.layer.cornerRadius = 16; _settingsButtonInternal.layer.masksToBounds = YES; _settingsButtonInternal.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9]; [_settingsButtonInternal setTitle:@"⚙︎" forState:UIControlStateNormal]; // 简单的齿轮符号 [_settingsButtonInternal setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [_settingsButtonInternal addTarget:self action:@selector(onSettings) forControlEvents:UIControlEventTouchUpInside]; } return _settingsButtonInternal; } - (UIButton *)globeButtonInternal { if (!_globeButtonInternal) { _globeButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem]; _globeButtonInternal.layer.cornerRadius = 16; _globeButtonInternal.layer.masksToBounds = YES; _globeButtonInternal.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9]; [_globeButtonInternal setTitle:@"🌐" forState:UIControlStateNormal]; [_globeButtonInternal setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; } return _globeButtonInternal; } #pragma mark - Globe (Input Mode Switch) // 根据宿主是否已提供系统切换键,决定是否显示地球按钮;并绑定系统事件。 - (void)kb_refreshGlobeVisibility { UIInputViewController *ivc = KBFindInputViewController(self); BOOL needSwitchKey = YES; if (ivc && [ivc respondsToSelector:@selector(needsInputModeSwitchKey)]) { needSwitchKey = ivc.needsInputModeSwitchKey; // YES 表示自定义键盘需要提供切换键 } self.globeButtonInternal.hidden = !needSwitchKey; // 重新调整 leftContainer 的左约束:若不需要地球键,则贴左边距 12 [self.leftContainer mas_remakeConstraints:^(MASConstraintMaker *make) { if (needSwitchKey) { make.left.equalTo(self.globeButtonInternal.mas_right).offset(8); } else { make.left.equalTo(self.mas_left).offset(12); } make.right.equalTo(self.settingsButtonInternal.mas_left).offset(-12); make.centerY.equalTo(self.mas_centerY); make.height.mas_equalTo(32); }]; // 绑定系统提供的输入法切换处理(点按切换、长按弹出列表) // 仅在需要时绑定,避免多余的事件转发 [self.globeButtonInternal removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents]; if (needSwitchKey && ivc) { SEL sel = NSSelectorFromString(@"handleInputModeListFromView:withEvent:"); if ([ivc respondsToSelector:sel]) { [self.globeButtonInternal addTarget:ivc action:sel forControlEvents:UIControlEventAllTouchEvents]; } else { // 回退:至少在点按时切换 [self.globeButtonInternal addTarget:ivc action:@selector(advanceToNextInputMode) forControlEvents:UIControlEventTouchUpInside]; } } } - (void)didMoveToWindow { [super didMoveToWindow]; [self kb_refreshGlobeVisibility]; } @end