From 11d8f78b1b502e622ad8a62997a3a4a4bb546f4d Mon Sep 17 00:00:00 2001 From: CodeST <694468528@qq.com> Date: Thu, 8 Jan 2026 20:04:23 +0800 Subject: [PATCH] 2 --- CustomKeyboard/KeyboardViewController.m | 40 ++++++++++++++++++++++++ CustomKeyboard/Resource/normal_them.zip | Bin 421787 -> 439993 bytes CustomKeyboard/View/KBKeyboardView.m | 40 ++++++++++++++++++++++++ keyBoard.xcodeproj/project.pbxproj | 8 ++--- 4 files changed, 84 insertions(+), 4 deletions(-) diff --git a/CustomKeyboard/KeyboardViewController.m b/CustomKeyboard/KeyboardViewController.m index 6156407..3d880ef 100644 --- a/CustomKeyboard/KeyboardViewController.m +++ b/CustomKeyboard/KeyboardViewController.m @@ -729,6 +729,20 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center, - (void)kb_applyTheme { KBSkinTheme *t = [KBSkinManager shared].current; UIImage *img = [[KBSkinManager shared] currentBackgroundImage]; + if ([self kb_isDefaultKeyboardTheme:t]) { + CGSize size = self.bgImageView.bounds.size; + if (size.width <= 0 || size.height <= 0) { + [self.view layoutIfNeeded]; + size = self.bgImageView.bounds.size; + } + if (size.width <= 0 || size.height <= 0) { + size = self.view.bounds.size; + } + if (size.width <= 0 || size.height <= 0) { + size = [UIScreen mainScreen].bounds.size; + } + img = [self kb_defaultGradientImageWithSize:size]; + } NSLog(@"⌨️[Keyboard] apply theme id=%@ hasBg=%d", t.skinId, (img != nil)); [self kb_logSkinDiagnosticsWithTheme:t backgroundImage:img]; self.bgImageView.image = img; @@ -752,6 +766,32 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center, } } +- (BOOL)kb_isDefaultKeyboardTheme:(KBSkinTheme *)theme { + NSString *skinId = theme.skinId ?: @""; + if (skinId.length == 0 || [skinId isEqualToString:@"default"]) { + return YES; + } + return [skinId isEqualToString:kKBDefaultSkinId]; +} + +- (UIImage *)kb_defaultGradientImageWithSize:(CGSize)size { + if (size.width <= 0 || size.height <= 0) { return nil; } + CAGradientLayer *layer = [CAGradientLayer layer]; + layer.frame = CGRectMake(0, 0, size.width, size.height); + layer.startPoint = CGPointMake(0.5, 0.0); + layer.endPoint = CGPointMake(0.5, 1.0); + layer.colors = @[ + (id)[UIColor colorWithHex:0xDEDFE4].CGColor, + (id)[UIColor colorWithHex:0xD1D3DB].CGColor + ]; + + UIGraphicsBeginImageContextWithOptions(size, YES, 0); + [layer renderInContext:UIGraphicsGetCurrentContext()]; + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return image; +} + - (void)kb_logSkinDiagnosticsWithTheme:(KBSkinTheme *)theme backgroundImage:(UIImage *)image { #if DEBUG diff --git a/CustomKeyboard/Resource/normal_them.zip b/CustomKeyboard/Resource/normal_them.zip index b3635b16ecf2fe7bf962b15d69ed3489894b5485..9c2b9416aaa75eadf041115ca720cf464151b121 100644 GIT binary patch delta 27174 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 A$^ZZW diff --git a/CustomKeyboard/View/KBKeyboardView.m b/CustomKeyboard/View/KBKeyboardView.m index 06782f8..61c57fc 100644 --- a/CustomKeyboard/View/KBKeyboardView.m +++ b/CustomKeyboard/View/KBKeyboardView.m @@ -128,6 +128,46 @@ static const CGFloat kKBLettersRow2EdgeSpacerMultiplier = 0.5; [self buildRow:self.row4 withRowConfig:rows[3]]; } +#pragma mark - Hit Test + +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { + UIView *hit = [super hitTest:point withEvent:event]; + if ([hit isKindOfClass:[KBKeyButton class]]) { + return hit; + } + if (hit == self || hit == self.row1 || hit == self.row2 || hit == self.row3 || hit == self.row4) { + KBKeyButton *btn = [self kb_nearestKeyButtonForPoint:point]; + if (btn) { return btn; } + } + return hit; +} + +- (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]; + 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; } + CGFloat dx = point.x - CGRectGetMidX(frame); + CGFloat dy = point.y - CGRectGetMidY(frame); + CGFloat dist = (dx * dx) + (dy * dy); + if (dist < bestDistance) { + bestDistance = dist; + best = btn; + } + } + } + return best; +} + #pragma mark - Key Model Construction // 创建当前布局下各行的 KBKey 列表 diff --git a/keyBoard.xcodeproj/project.pbxproj b/keyBoard.xcodeproj/project.pbxproj index d9d7494..b1263ed 100644 --- a/keyBoard.xcodeproj/project.pbxproj +++ b/keyBoard.xcodeproj/project.pbxproj @@ -172,7 +172,7 @@ 04C6EADD2EAF8CEB0089C901 /* KBToolBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 04C6EADC2EAF8CEB0089C901 /* KBToolBar.m */; }; 04D1F6B22EDFF10A00B12345 /* KBSkinInstallBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 04D1F6B12EDFF10A00B12345 /* KBSkinInstallBridge.m */; }; 04D1F6B32EDFF10A00B12345 /* KBSkinInstallBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 04D1F6B12EDFF10A00B12345 /* KBSkinInstallBridge.m */; }; - 04E1617A2F0FB1320022C23B /* normal_them.zip in Resources */ = {isa = PBXBuildFile; fileRef = 04E161792F0FB1320022C23B /* normal_them.zip */; }; + 04E1617C2F0FCA050022C23B /* normal_them.zip in Resources */ = {isa = PBXBuildFile; fileRef = 04E1617B2F0FCA050022C23B /* normal_them.zip */; }; 04FC95672EB0546C007BD342 /* KBKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95652EB0546C007BD342 /* KBKey.m */; }; 04FC956A2EB05497007BD342 /* KBKeyButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95692EB05497007BD342 /* KBKeyButton.m */; }; 04FC956D2EB054B7007BD342 /* KBKeyboardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC956C2EB054B7007BD342 /* KBKeyboardView.m */; }; @@ -540,7 +540,7 @@ 04C6EAE12EAF940F0089C901 /* KBPermissionViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBPermissionViewController.m; sourceTree = ""; }; 04D1F6B02EDFF10A00B12345 /* KBSkinInstallBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinInstallBridge.h; sourceTree = ""; }; 04D1F6B12EDFF10A00B12345 /* KBSkinInstallBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinInstallBridge.m; sourceTree = ""; }; - 04E161792F0FB1320022C23B /* normal_them.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = normal_them.zip; sourceTree = ""; }; + 04E1617B2F0FCA050022C23B /* normal_them.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = normal_them.zip; sourceTree = ""; }; 04FC953A2EAFAE56007BD342 /* KeyBoardPrefixHeader.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyBoardPrefixHeader.pch; sourceTree = ""; }; 04FC95642EB0546C007BD342 /* KBKey.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBKey.h; sourceTree = ""; }; 04FC95652EB0546C007BD342 /* KBKey.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBKey.m; sourceTree = ""; }; @@ -691,7 +691,7 @@ 041007D02ECE010100D203BB /* Resource */ = { isa = PBXGroup; children = ( - 04E161792F0FB1320022C23B /* normal_them.zip */, + 04E1617B2F0FCA050022C23B /* normal_them.zip */, A1B2C3EC2F20000000000001 /* kb_words.txt */, A1B2C3F02F20000000000002 /* kb_keyboard_layout_config.json */, 0498BDF42EEC50EE006CC1D5 /* emoji_categories.json */, @@ -1826,7 +1826,7 @@ files = ( 04A9FE202EB893F10020DB6D /* Localizable.strings in Resources */, 041007D42ECE012500D203BB /* 002.zip in Resources */, - 04E1617A2F0FB1320022C23B /* normal_them.zip in Resources */, + 04E1617C2F0FCA050022C23B /* normal_them.zip in Resources */, 041007D22ECE012000D203BB /* KBSkinIconMap.strings in Resources */, A1B2C3ED2F20000000000001 /* kb_words.txt in Resources */, A1B2C3F12F20000000000002 /* kb_keyboard_layout_config.json in Resources */,