diff --git a/CustomKeyboard/View/KBKeyboardView.m b/CustomKeyboard/View/KBKeyboardView.m index 61c57fc..7919ef8 100644 --- a/CustomKeyboard/View/KBKeyboardView.m +++ b/CustomKeyboard/View/KBKeyboardView.m @@ -135,27 +135,42 @@ static const CGFloat kKBLettersRow2EdgeSpacerMultiplier = 0.5; if ([hit isKindOfClass:[KBKeyButton class]]) { return hit; } - if (hit == self || hit == self.row1 || hit == self.row2 || hit == self.row3 || hit == self.row4) { + if ([self kb_isHitInsideKeyRows:hit]) { KBKeyButton *btn = [self kb_nearestKeyButtonForPoint:point]; if (btn) { return btn; } } return hit; } +- (BOOL)kb_isHitInsideKeyRows:(UIView *)hitView { + if (!hitView) { return NO; } + if (hitView == self) { return YES; } + if ([hitView isDescendantOfView:self.row1]) { return YES; } + if ([hitView isDescendantOfView:self.row2]) { return YES; } + if ([hitView isDescendantOfView:self.row3]) { return YES; } + if ([hitView isDescendantOfView:self.row4]) { return YES; } + return NO; +} + - (KBKeyButton *)kb_nearestKeyButtonForPoint:(CGPoint)point { - // 扩大按键的可点击区域,优先响应间隙点击(贴近系统键盘手感)。 - CGFloat slopX = KBFit(8.0f); - CGFloat slopY = KBFit(4.0f); KBKeyButton *best = nil; CGFloat bestDistance = CGFLOAT_MAX; NSArray *rows = @[self.row1, self.row2, self.row3, self.row4]; + + UIView *targetRow = nil; for (UIView *row in rows) { - for (UIView *view in row.subviews) { - if (![view isKindOfClass:[KBKeyButton class]]) { continue; } - KBKeyButton *btn = (KBKeyButton *)view; - CGRect frame = [self convertRect:btn.frame fromView:row]; - CGRect hitFrame = CGRectInset(frame, -slopX, -slopY); - if (!CGRectContainsPoint(hitFrame, point)) { continue; } + CGRect rowFrame = [self convertRect:row.bounds fromView:row]; + if (CGRectContainsPoint(rowFrame, point)) { + targetRow = row; + break; + } + } + + NSArray *candidateRows = targetRow ? @[targetRow] : rows; + for (UIView *row in candidateRows) { + NSArray *buttons = [self kb_collectKeyButtonsInView:row]; + for (KBKeyButton *btn in buttons) { + CGRect frame = [self convertRect:btn.frame fromView:btn.superview]; CGFloat dx = point.x - CGRectGetMidX(frame); CGFloat dy = point.y - CGRectGetMidY(frame); CGFloat dist = (dx * dx) + (dy * dy); @@ -168,6 +183,26 @@ static const CGFloat kKBLettersRow2EdgeSpacerMultiplier = 0.5; return best; } +- (NSArray *)kb_collectKeyButtonsInView:(UIView *)view { + if (!view) { return @[]; } + NSMutableArray *buttons = [NSMutableArray array]; + [self kb_collectKeyButtonsInView:view into:buttons]; + return buttons.copy; +} + +- (void)kb_collectKeyButtonsInView:(UIView *)view + into:(NSMutableArray *)buttons { + for (UIView *sub in view.subviews) { + if ([sub isKindOfClass:[KBKeyButton class]]) { + [buttons addObject:(KBKeyButton *)sub]; + continue; + } + if (sub.subviews.count > 0) { + [self kb_collectKeyButtonsInView:sub into:buttons]; + } + } +} + #pragma mark - Key Model Construction // 创建当前布局下各行的 KBKey 列表