This commit is contained in:
2025-11-18 20:53:47 +08:00
parent 254e65906a
commit 3dcc4932c3
109 changed files with 1432 additions and 84 deletions

View File

@@ -20,13 +20,29 @@ typedef NS_ENUM(NSInteger, KBKeyType) {
KBKeyTypeSymbolsToggle // 数字面板内的“#+=/123”切换
};
/// 字母键的大小写变体标记(非字母键使用 KBKeyCaseVariantNone
typedef NS_ENUM(NSInteger, KBKeyCaseVariant) {
KBKeyCaseVariantNone = 0,
KBKeyCaseVariantLower = 1,
KBKeyCaseVariantUpper = 2,
};
@interface KBKey : NSObject
@property (nonatomic, assign) KBKeyType type;
@property (nonatomic, copy) NSString *title; // 显示标题
@property (nonatomic, copy) NSString *output; // 字符键插入的文本
/// 逻辑按键标识,用于皮肤映射(如 @"letter_q" @"space" @"backspace"
@property (nonatomic, copy, nullable) NSString *identifier;
/// 字母键的大小写变体(便于皮肤为大小写准备不同图)
@property (nonatomic, assign) KBKeyCaseVariant caseVariant;
+ (instancetype)keyWithTitle:(NSString *)title output:(NSString *)output;
+ (instancetype)keyWithTitle:(NSString *)title type:(KBKeyType)type;
/// 通用构造方法:用于指定 identifier便于皮肤做精细控制
+ (instancetype)keyWithIdentifier:(nullable NSString *)identifier
title:(NSString *)title
output:(NSString *)output
type:(KBKeyType)type;
@end

View File

@@ -12,6 +12,7 @@
k.type = KBKeyTypeCharacter;
k.title = title ?: @"";
k.output = output ?: title ?: @"";
k.caseVariant = KBKeyCaseVariantNone;
return k;
}
@@ -20,8 +21,21 @@
k.type = type;
k.title = title ?: @"";
k.output = @"";
k.caseVariant = KBKeyCaseVariantNone;
return k;
}
+ (instancetype)keyWithIdentifier:(NSString *)identifier
title:(NSString *)title
output:(NSString *)output
type:(KBKeyType)type {
KBKey *k = [[KBKey alloc] init];
k.type = type;
k.identifier = identifier;
k.title = title ?: @"";
k.output = output ?: @"";
k.caseVariant = KBKeyCaseVariantNone;
return k;
}
@end

View File

@@ -17,4 +17,7 @@
/// 根据选中/高亮等状态刷新外观
- (void)refreshStateAppearance;
/// 根据当前皮肤与按键标识,应用图标和文字显隐等细节
- (void)applyThemeForCurrentKey;
@end

View File

@@ -7,6 +7,10 @@
#import "KBKey.h"
#import "KBSkinManager.h"
@interface KBKeyButton ()
@property (nonatomic, strong) UIImageView *iconView;
@end
@implementation KBKeyButton
- (instancetype)initWithFrame:(CGRect)frame {
@@ -29,6 +33,34 @@
self.layer.shadowOffset = CGSizeMake(0, 1);
self.layer.shadowRadius = 1.5;
[self refreshStateAppearance];
//
if (!self.iconView) {
UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectZero];
//
iv.contentMode = UIViewContentModeScaleAspectFill;
iv.clipsToBounds = YES;
iv.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:iv];
//
[NSLayoutConstraint activateConstraints:@[
[iv.topAnchor constraintEqualToAnchor:self.topAnchor],
[iv.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
[iv.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
[iv.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
]];
self.iconView = iv;
//
self.titleEdgeInsets = UIEdgeInsetsZero;
[self bringSubviewToFront:self.titleLabel];
}
}
- (void)setKey:(KBKey *)key {
_key = key;
//
[self applyThemeForCurrentKey];
}
- (void)setHighlighted:(BOOL)highlighted {
@@ -56,4 +88,19 @@
}
}
- (void)applyThemeForCurrentKey {
//
NSString *identifier = self.key.identifier;
BOOL hideText = [[KBSkinManager shared] shouldHideKeyTextForIdentifier:identifier];
self.titleLabel.hidden = hideText;
//
// - identifier: letter_q
// - caseVariant: 0/1/2 => //
NSInteger variant = (NSInteger)self.key.caseVariant;
UIImage *iconImg = [[KBSkinManager shared] iconImageForKeyIdentifier:identifier caseVariant:variant];
self.iconView.image = iconImg;
self.iconView.hidden = (iconImg == nil);
}
@end

View File

@@ -96,16 +96,41 @@
if (!self.symbolsMoreOn) {
// 123
r1 = @[ [KBKey keyWithTitle:@"1" output:@"1"], [KBKey keyWithTitle:@"2" output:@"2"], [KBKey keyWithTitle:@"3" output:@"3"],
[KBKey keyWithTitle:@"4" output:@"4"], [KBKey keyWithTitle:@"5" output:@"5"], [KBKey keyWithTitle:@"6" output:@"6"],
[KBKey keyWithTitle:@"7" output:@"7"], [KBKey keyWithTitle:@"8" output:@"8"], [KBKey keyWithTitle:@"9" output:@"9"], [KBKey keyWithTitle:@"0" output:@"0"] ];
r2 = @[ [KBKey keyWithTitle:@"-" output:@"-"], [KBKey keyWithTitle:@"/" output:@"/"], [KBKey keyWithTitle:@":" output:@":"],
[KBKey keyWithTitle:@";" output:@";"], [KBKey keyWithTitle:@"(" output:@"("], [KBKey keyWithTitle:@")" output:@")"],
[KBKey keyWithTitle:@"$" output:@"$"], [KBKey keyWithTitle:@"&" output:@"&"], [KBKey keyWithTitle:@"@" output:@"@"], [KBKey keyWithTitle:@"\"" output:@"\""] ];
r3 = @[ [KBKey keyWithTitle:@"#+=" type:KBKeyTypeSymbolsToggle],
[KBKey keyWithTitle:@"," output:@","], [KBKey keyWithTitle:@"." output:@"."], [KBKey keyWithTitle:@"?" output:@"?"],
[KBKey keyWithTitle:@"!" output:@"!"], [KBKey keyWithTitle:@"'" output:@"'"],
[KBKey keyWithTitle:@"" type:KBKeyTypeBackspace] ];
r1 = @[ [KBKey keyWithTitle:@"1" output:@"1"],
[KBKey keyWithTitle:@"2" output:@"2"],
[KBKey keyWithTitle:@"3" output:@"3"],
[KBKey keyWithTitle:@"4" output:@"4"],
[KBKey keyWithTitle:@"5" output:@"5"],
[KBKey keyWithTitle:@"6" output:@"6"],
[KBKey keyWithTitle:@"7" output:@"7"],
[KBKey keyWithTitle:@"8" output:@"8"],
[KBKey keyWithTitle:@"9" output:@"9"],
[KBKey keyWithTitle:@"0" output:@"0"] ];
r2 = @[ [KBKey keyWithTitle:@"-" output:@"-"],
[KBKey keyWithTitle:@"/" output:@"/"],
[KBKey keyWithTitle:@":" output:@":"],
[KBKey keyWithTitle:@";" output:@";"],
[KBKey keyWithTitle:@"(" output:@"("],
[KBKey keyWithTitle:@")" output:@")"],
[KBKey keyWithTitle:@"$" output:@"$"],
[KBKey keyWithTitle:@"&" output:@"&"],
[KBKey keyWithTitle:@"@" output:@"@"],
[KBKey keyWithTitle:@"\"" output:@"\""] ];
// #+=退
KBKey *toggle = [KBKey keyWithIdentifier:@"symbols_toggle_more"
title:@"#+="
output:@""
type:KBKeyTypeSymbolsToggle];
KBKey *comma = [KBKey keyWithTitle:@"," output:@","];
KBKey *dot = [KBKey keyWithTitle:@"." output:@"."];
KBKey *q = [KBKey keyWithTitle:@"?" output:@"?"];
KBKey *ex = [KBKey keyWithTitle:@"!" output:@"!"];
KBKey *quote = [KBKey keyWithTitle:@"'" output:@"'"];
KBKey *back = [KBKey keyWithIdentifier:@"backspace"
title:@"⌫"
output:@""
type:KBKeyTypeBackspace];
r3 = @[ toggle, comma, dot, q, ex, quote, back ];
} else {
// #+=123
r1 = @[ [KBKey keyWithTitle:@"[" output:@"["], [KBKey keyWithTitle:@"]" output:@"]"], [KBKey keyWithTitle:@"{" output:@"{"],
@@ -116,16 +141,40 @@
[KBKey keyWithTitle:@"~" output:@"~"], [KBKey keyWithTitle:@"<" output:@"<"], [KBKey keyWithTitle:@">" output:@">"],
[KBKey keyWithTitle:@"$" output:@"$"], [KBKey keyWithTitle:@"€" output:@"€"], [KBKey keyWithTitle:@"£" output:@"£"],
[KBKey keyWithTitle:@"•" output:@"•"] ];
r3 = @[ [KBKey keyWithTitle:@"123" type:KBKeyTypeSymbolsToggle],
[KBKey keyWithTitle:@"," output:@","], [KBKey keyWithTitle:@"." output:@"."], [KBKey keyWithTitle:@"?" output:@"?"],
[KBKey keyWithTitle:@"!" output:@"!"], [KBKey keyWithTitle:@"'" output:@"'"],
[KBKey keyWithTitle:@"⌫" type:KBKeyTypeBackspace] ];
KBKey *toggle = [KBKey keyWithIdentifier:@"symbols_toggle_123"
title:@"123"
output:@""
type:KBKeyTypeSymbolsToggle];
KBKey *comma = [KBKey keyWithTitle:@"," output:@","];
KBKey *dot = [KBKey keyWithTitle:@"." output:@"."];
KBKey *q = [KBKey keyWithTitle:@"?" output:@"?"];
KBKey *ex = [KBKey keyWithTitle:@"!" output:@"!"];
KBKey *quote = [KBKey keyWithTitle:@"'" output:@"'"];
KBKey *back = [KBKey keyWithIdentifier:@"backspace"
title:@"⌫"
output:@""
type:KBKeyTypeBackspace];
r3 = @[ toggle, comma, dot, q, ex, quote, back ];
}
NSArray *r4 = @[ [KBKey keyWithTitle:@"abc" type:KBKeyTypeModeChange],
[KBKey keyWithTitle:@"AI" type:KBKeyTypeCustom],
[KBKey keyWithTitle:@"space" type:KBKeyTypeSpace],
[KBKey keyWithTitle:KBLocalized(@"Send") type:KBKeyTypeReturn] ];
KBKey *modeABC = [KBKey keyWithIdentifier:@"mode_abc"
title:@"abc"
output:@""
type:KBKeyTypeModeChange];
KBKey *customAI = [KBKey keyWithIdentifier:@"ai"
title:@"AI"
output:@""
type:KBKeyTypeCustom];
KBKey *space = [KBKey keyWithIdentifier:@"space"
title:@"space"
output:@" "
type:KBKeyTypeSpace];
KBKey *ret = [KBKey keyWithIdentifier:@"return"
title:KBLocalized(@"Send")
output:@"\n"
type:KBKeyTypeReturn];
NSArray *r4 = @[ modeABC, customAI, space, ret ];
return @[r1, r2, r3, r4];
}
@@ -139,27 +188,67 @@
// Shift
for (NSString *s in r1) {
NSString *shown = self.shiftOn ? s : s.lowercaseString;
[row1 addObject:[KBKey keyWithTitle:shown output:shown]];
NSString *identifier = [NSString stringWithFormat:@"letter_%@", s.lowercaseString];
KBKey *k = [KBKey keyWithIdentifier:identifier
title:shown
output:shown
type:KBKeyTypeCharacter];
k.caseVariant = self.shiftOn ? KBKeyCaseVariantUpper : KBKeyCaseVariantLower;
[row1 addObject:k];
}
NSMutableArray *row2 = [NSMutableArray arrayWithCapacity:r2.count];
for (NSString *s in r2) {
NSString *shown = self.shiftOn ? s : s.lowercaseString;
[row2 addObject:[KBKey keyWithTitle:shown output:shown]];
NSString *identifier = [NSString stringWithFormat:@"letter_%@", s.lowercaseString];
KBKey *k = [KBKey keyWithIdentifier:identifier
title:shown
output:shown
type:KBKeyTypeCharacter];
k.caseVariant = self.shiftOn ? KBKeyCaseVariantUpper : KBKeyCaseVariantLower;
[row2 addObject:k];
}
NSMutableArray *row3 = [NSMutableArray array];
[row3 addObject:[KBKey keyWithTitle:@"⇧" type:KBKeyTypeShift]];
KBKey *shift = [KBKey keyWithIdentifier:@"shift"
title:@"⇧"
output:@""
type:KBKeyTypeShift];
[row3 addObject:shift];
for (NSString *s in r3chars) {
NSString *shown = self.shiftOn ? s : s.lowercaseString;
[row3 addObject:[KBKey keyWithTitle:shown output:shown]];
NSString *identifier = [NSString stringWithFormat:@"letter_%@", s.lowercaseString];
KBKey *k = [KBKey keyWithIdentifier:identifier
title:shown
output:shown
type:KBKeyTypeCharacter];
k.caseVariant = self.shiftOn ? KBKeyCaseVariantUpper : KBKeyCaseVariantLower;
[row3 addObject:k];
}
[row3 addObject:[KBKey keyWithTitle:@"⌫" type:KBKeyTypeBackspace]];
KBKey *backspace = [KBKey keyWithIdentifier:@"backspace"
title:@"⌫"
output:@""
type:KBKeyTypeBackspace];
[row3 addObject:backspace];
NSArray *row4 = @[ [KBKey keyWithTitle:@"123" type:KBKeyTypeModeChange],
[KBKey keyWithTitle:@"AI" type:KBKeyTypeCustom],
[KBKey keyWithTitle:@"space" type:KBKeyTypeSpace],
[KBKey keyWithTitle:KBLocalized(@"Send") type:KBKeyTypeReturn] ];
KBKey *mode123 = [KBKey keyWithIdentifier:@"mode_123"
title:@"123"
output:@""
type:KBKeyTypeModeChange];
KBKey *customAI = [KBKey keyWithIdentifier:@"ai"
title:@"AI"
output:@""
type:KBKeyTypeCustom];
KBKey *space = [KBKey keyWithIdentifier:@"space"
title:@"space"
output:@" "
type:KBKeyTypeSpace];
KBKey *ret = [KBKey keyWithIdentifier:@"return"
title:KBLocalized(@"Send")
output:@"\n"
type:KBKeyTypeReturn];
NSArray *row4 = @[ mode123, customAI, space, ret ];
return @[row1.copy, row2.copy, row3.copy, row4];
}