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

227 lines
8.3 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.

//
// KBFunctionBarView.m
// CustomKeyboard
//
// Created by Mac on 2025/10/28.
// 功能 - barview
#import "KBFunctionBarView.h"
#import "Masonry.h"
#import "KBResponderUtils.h" // 查找 UIInputViewController用于系统切换输入法
@interface KBFunctionBarView ()
@property (nonatomic, strong) UIView *leftContainer; // 左侧按钮容器
@property (nonatomic, strong) UIView *rightContainer; // 右侧按钮容器
@property (nonatomic, strong) NSArray<UIButton *> *leftButtonsInternal;
@property (nonatomic, strong) NSArray<UIButton *> *rightButtonsInternal;
@property (nonatomic, strong) UIButton *globeButtonInternal; // 可选:系统“切换输入法”键
@end
@implementation KBFunctionBarView
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor clearColor];
_leftTitles = @[@"ABC"];
_rightTitles = @[@"Upgrade VIP"];
[self buildUI];
}
return self;
}
#pragma mark - Public
- (NSArray<UIButton *> *)leftButtons { return self.leftButtonsInternal; }
- (NSArray<UIButton *> *)rightButtons { return self.rightButtonsInternal; }
#pragma mark - UI
- (void)buildUI {
// 左右两个容器,方便分别布局
[self addSubview:self.leftContainer];
[self addSubview:self.globeButtonInternal];
[self addSubview:self.rightContainer];
[self.rightContainer mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.mas_right).offset(-12);
make.centerY.equalTo(self.mas_centerY);
make.height.mas_equalTo(36);
}];
// 左侧地球键(按需显示)
[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.rightContainer.mas_left).offset(-12);
make.centerY.equalTo(self.mas_centerY);
make.height.mas_equalTo(36);
}];
// 左侧4个等宽按钮
NSMutableArray<UIButton *> *leftBtns = [NSMutableArray arrayWithCapacity:4];
UIView *prev = nil;
for (NSInteger i = 0; i < self.leftTitles.count; i++) {
UIButton *btn = [self buildButtonWithTitle:(i < self.leftTitles.count ? self.leftTitles[i] : [NSString stringWithFormat:@"L%ld", (long)i])];
btn.tag = 100 + i;
[btn addTarget:self action:@selector(onLeftTap:) forControlEvents:UIControlEventTouchUpInside];
[self.leftContainer addSubview:btn];
[btn mas_makeConstraints:^(MASConstraintMaker *make) {
if (prev) {
make.left.equalTo(prev.mas_right).offset(8);
make.width.equalTo(prev);
} else {
make.left.equalTo(self.leftContainer.mas_left);
}
make.top.bottom.equalTo(self.leftContainer);
}];
prev = btn;
[leftBtns addObject:btn];
}
[prev mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.leftContainer.mas_right);
}];
self.leftButtonsInternal = leftBtns.copy;
// 右侧N个按钮靠右、两两等宽
NSMutableArray<UIButton *> *rightBtns = [NSMutableArray arrayWithCapacity:3];
for (NSInteger i = 0; i < self.rightTitles.count; i++) {
UIButton *btn = [self buildButtonWithTitle:(i < self.rightTitles.count ? self.rightTitles[i] : [NSString stringWithFormat:@"R%ld", (long)i])];
btn.tag = 200 + i;
[self.rightContainer addSubview:btn];
[btn addTarget:self action:@selector(onRightTap:) forControlEvents:UIControlEventTouchUpInside];
[rightBtns addObject:btn];
}
// 从右往左链式布局,保证整体靠右;支持 1/2/3... 任意数量
UIView *prevRight = nil; // 指向右侧已布局的按钮
for (NSInteger i = rightBtns.count - 1; i >= 0; i--) {
UIButton *btn = rightBtns[i];
[btn mas_makeConstraints:^(MASConstraintMaker *make) {
if (!prevRight) {
// 最右侧按钮贴右
make.right.equalTo(self.rightContainer.mas_right);
} else {
// 其余按钮紧挨左侧兄弟,且与其等宽
make.right.equalTo(prevRight.mas_left).offset(-8);
make.width.equalTo(prevRight);
}
make.top.bottom.equalTo(self.rightContainer);
}];
prevRight = btn;
}
// 最左侧一个不超出容器左边(允许根据内容自然宽度收缩)
if (prevRight) {
[prevRight mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.greaterThanOrEqualTo(self.rightContainer.mas_left);
}];
}
self.rightButtonsInternal = rightBtns.copy;
// 初始刷新地球键可见性与事件绑定
[self kb_refreshGlobeVisibility];
}
#pragma mark - Actions
- (void)onLeftTap:(UIButton *)sender {
NSInteger idx = sender.tag - 100;
if ([self.delegate respondsToSelector:@selector(functionBarView:didTapLeftAtIndex:)]) {
[self.delegate functionBarView:self didTapLeftAtIndex:idx];
}
}
- (void)onRightTap:(UIButton *)sender {
NSInteger idx = sender.tag - 200;
if ([self.delegate respondsToSelector:@selector(functionBarView:didTapRightAtIndex:)]) {
[self.delegate functionBarView:self didTapRightAtIndex:idx];
}
}
- (UIButton *)buildButtonWithTitle:(NSString *)title {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
btn.layer.cornerRadius = 18;
btn.layer.masksToBounds = YES;
btn.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9];
btn.titleLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium];
[btn setTitle:title forState:UIControlStateNormal];
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
return btn;
}
#pragma mark - Lazy
- (UIView *)leftContainer {
if (!_leftContainer) {
_leftContainer = [[UIView alloc] init];
}
return _leftContainer;
}
- (UIView *)rightContainer {
if (!_rightContainer) {
_rightContainer = [[UIView alloc] init];
}
return _rightContainer;
}
- (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;
}
self.globeButtonInternal.hidden = !needSwitchKey;
// 左容器左约束:根据是否显示地球键动态调整
[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.rightContainer.mas_left).offset(-12);
make.centerY.equalTo(self.mas_centerY);
make.height.mas_equalTo(36);
}];
// 绑定系统输入法切换事件
[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