Files
keyboard/CustomKeyboard/View/KBToolBar.m
2025-11-05 20:11:10 +08:00

214 lines
7.9 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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<UIButton *> *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<UIButton *> *)leftButtons {
return self.leftButtonsInternal;
}
- (UIButton *)settingsButton {
return self.settingsButtonInternal;
}
- (void)setLeftButtonTitles:(NSArray<NSString *> *)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<UIButton *> *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