diff --git a/CustomKeyboard/View/KBKeyBoardMainView.m b/CustomKeyboard/View/KBKeyBoardMainView.m index 40acc9c..0c5dff5 100644 --- a/CustomKeyboard/View/KBKeyBoardMainView.m +++ b/CustomKeyboard/View/KBKeyBoardMainView.m @@ -39,7 +39,8 @@ [self addSubview:self.keyboardView]; [self.keyboardView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.equalTo(self); - make.top.equalTo(self.topBar.mas_bottom).offset(4); +// make.top.equalTo(self.topBar.mas_bottom).offset(4); + make.height.mas_equalTo(200); make.bottom.equalTo(self.mas_bottom).offset(-4); }]; diff --git a/CustomKeyboard/View/KBKeyboardView.m b/CustomKeyboard/View/KBKeyboardView.m index 50dbedb..9ffe4f8 100644 --- a/CustomKeyboard/View/KBKeyboardView.m +++ b/CustomKeyboard/View/KBKeyboardView.m @@ -54,7 +54,7 @@ [self.row1 mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.mas_top).offset(8); make.left.right.equalTo(self); - make.height.mas_equalTo(44); + make.height.mas_equalTo(40); }]; [self.row2 mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.row1.mas_bottom).offset(vSpacing); @@ -276,6 +276,10 @@ } - (void)buildRow:(UIView *)row withKeys:(NSArray *)keys edgeSpacerMultiplier:(CGFloat)edgeSpacerMultiplier { + // 第 4 行(底部控制行)使用单独的布局规则: + // 123/ABC、AI、Send 给定尺寸,Space 自动吃掉剩余宽度。 + BOOL isBottomControlRow = [self kb_isBottomControlRowWithKeys:keys]; + CGFloat hInset = 6; // 行左右内边距 CGFloat spacing = 0; // 键与键之间的间距 UIView *previous = nil; @@ -352,6 +356,7 @@ previous = btn; } + // 右侧使用内边距或右占位 [previous mas_makeConstraints:^(MASConstraintMaker *make) { if (rightSpacer) { @@ -361,6 +366,13 @@ } }]; + // 底部控制行:在第一轮已完成左右约束的前提下,仅给 123/ABC、AI、Send 指定宽度, + // Space 不加宽度约束,让其自动填充剩余空间。 + if (isBottomControlRow) { + [self kb_applyBottomControlRowWidthInRow:row]; + return; + } + // 第二遍:以首个字符键为基准,统一设置特殊键宽度倍数 KBKeyButton *firstChar = nil; BOOL hasCharacterInRow = NO; @@ -402,6 +414,7 @@ // 一类键强制宽高比 1:1: // - 第三行:Shift、Backspace // - 第四行:123/ABC(ModeChange)、#+=(SymbolsToggle)、AI(Custom) + // (真正的底部控制行在上面已单独处理,这里主要服务于第三行的 #+= 等) BOOL isBottomModeKey = (b.key.type == KBKeyTypeModeChange) || (b.key.type == KBKeyTypeSymbolsToggle) || (b.key.type == KBKeyTypeCustom); @@ -409,7 +422,7 @@ b.key.type == KBKeyTypeBackspace || isBottomModeKey) { [b mas_makeConstraints:^(MASConstraintMaker *make) { - make.width.equalTo(b.mas_height); // 宽度 = 高度,做成正方形 + make.width.equalTo(b.mas_height).multipliedBy(1.2); // 宽度 = 高度,做成正方形 }]; continue; } @@ -445,6 +458,79 @@ } } +#pragma mark - Row Helpers (Bottom Control Row) + +// 判断是否为底部控制行:包含 Space + Return,且有 ModeChange/SymbolsToggle, +// 并且不再含字符键。 +- (BOOL)kb_isBottomControlRowWithKeys:(NSArray *)keys { + BOOL hasSpace = NO; + BOOL hasReturn = NO; + BOOL hasModeOrSymbols = NO; + for (KBKey *k in keys) { + if (k.type == KBKeyTypeCharacter) { + return NO; + } + if (k.type == KBKeyTypeSpace) { + hasSpace = YES; + } else if (k.type == KBKeyTypeReturn) { + hasReturn = YES; + } else if (k.type == KBKeyTypeModeChange || k.type == KBKeyTypeSymbolsToggle) { + hasModeOrSymbols = YES; + } + } + return hasSpace && hasReturn && hasModeOrSymbols; +} + +// 为底部控制行设置宽度: +// - 123/ABC、AI:正方形(宽 = 行高) +// - Send:宽 = 模式键宽度的 2.4 倍 +// - Space:不加宽度约束,依靠左右约束自动填充剩余空间。 +- (void)kb_applyBottomControlRowWidthInRow:(UIView *)row { + KBKeyButton *modeBtn = nil; + KBKeyButton *aiBtn = nil; + KBKeyButton *spaceBtn = nil; + KBKeyButton *retBtn = nil; + + for (UIView *v in row.subviews) { + if (![v isKindOfClass:[KBKeyButton class]]) continue; + KBKeyButton *b = (KBKeyButton *)v; + switch (b.key.type) { + case KBKeyTypeModeChange: + case KBKeyTypeSymbolsToggle: + modeBtn = b; + break; + case KBKeyTypeCustom: + aiBtn = b; + break; + case KBKeyTypeSpace: + spaceBtn = b; + break; + case KBKeyTypeReturn: + retBtn = b; + break; + default: + break; + } + } + + if (!modeBtn || !aiBtn || !spaceBtn || !retBtn) { + return; + } + + // 行高由外部约束为固定值(等于 row1 高度),这里用行高作为“正方形”的边长。 + [modeBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.equalTo(row.mas_height).multipliedBy(1.2); + }]; + [aiBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.equalTo(row.mas_height).multipliedBy(1.2); + }]; + [retBtn mas_makeConstraints:^(MASConstraintMaker *make) { + // Send 按钮:宽度为模式键的 2.4 倍 + make.width.equalTo(modeBtn.mas_width).multipliedBy(2); + }]; + // Space 不设置宽度;通过此前已建立的左右约束自动占满剩余宽度。 +} + #pragma mark - Actions - (void)onKeyTapped:(KBKeyButton *)sender { @@ -485,7 +571,7 @@ CGFloat centerX = CGRectGetMidX(btnFrameInSelf); CGFloat centerY = CGRectGetMinY(btnFrameInSelf) - previewHeight * 0.6; - self.previewView.frame = CGRectMake(0, 0, previewWidth, previewHeight); + self.previewView.frame = CGRectMake(0, 0, 40, previewHeight); self.previewView.center = CGPointMake(centerX, centerY); self.previewView.alpha = 0.0; self.previewView.hidden = NO;