Files
keyboard/CustomKeyboard/View/KBKeyButton.m

232 lines
9.0 KiB
Mathematica
Raw Normal View History

2025-10-28 10:18:10 +08:00
//
// KBKeyButton.m
// CustomKeyboard
//
#import "KBKeyButton.h"
#import "KBKey.h"
2025-11-04 21:01:46 +08:00
#import "KBSkinManager.h"
2025-10-28 10:18:10 +08:00
2025-11-18 20:53:47 +08:00
@interface KBKeyButton ()
2025-11-20 21:11:27 +08:00
// 便 KBKeyboardView
@property (nonatomic, weak, readonly) UIView *kb_keyboardContainer;
@property (nonatomic, strong) UIImageView *normalImageView; ///
@property (nonatomic, strong) UIColor *baseBackgroundColor; /// / normalImageView
2025-11-18 20:53:47 +08:00
@end
2025-10-28 10:18:10 +08:00
@implementation KBKeyButton
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self addSubview:self.normalImageView];
self.normalImageView.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[self.normalImageView.topAnchor constraintEqualToAnchor:self.topAnchor],
[self.normalImageView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
[self.normalImageView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:2],
[self.normalImageView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-2],
]];
2025-10-28 10:18:10 +08:00
[self applyDefaultStyle];
}
return self;
}
- (void)applyDefaultStyle {
2025-11-04 21:01:46 +08:00
self.titleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightSemibold];
KBSkinTheme *t = [KBSkinManager shared].current;
[self setTitleColor:t.keyTextColor forState:UIControlStateNormal];
[self setTitleColor:t.keyTextColor forState:UIControlStateHighlighted];
// normalImageView
self.backgroundColor = [UIColor clearColor];
2025-10-28 10:18:10 +08:00
self.layer.cornerRadius = 6.0; //
self.layer.masksToBounds = NO;
self.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.1].CGColor; //
self.layer.shadowOpacity = 1.0;
self.layer.shadowOffset = CGSizeMake(0, 1);
self.layer.shadowRadius = 1.5;
// 使
2025-10-28 20:11:40 +08:00
[self refreshStateAppearance];
2025-11-18 20:53:47 +08:00
//
if (!self.iconView) {
UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectZero];
//
2025-11-20 19:57:11 +08:00
iv.contentMode = UIViewContentModeScaleToFill;
2025-11-18 20:53:47 +08:00
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 constant:2],
[iv.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-2],
2025-11-18 20:53:47 +08:00
]];
self.iconView = iv;
//
self.titleEdgeInsets = UIEdgeInsetsZero;
[self bringSubviewToFront:self.titleLabel];
}
}
- (void)setKey:(KBKey *)key {
_key = key;
2025-10-28 10:18:10 +08:00
}
- (void)setHighlighted:(BOOL)highlighted {
[super setHighlighted:highlighted];
2025-11-20 20:36:31 +08:00
//
//
CGFloat scale = highlighted ? 0.9 : 1.0; // 0.9~0.95
// normalImageView
BOOL hasIcon = (self.iconView.image != nil);
UIColor *normalBgColor = self.baseBackgroundColor ?: [UIColor whiteColor];
UIColor *highlightBgColor = [self kb_darkerColorForColor:normalBgColor];
2025-11-20 20:36:31 +08:00
[UIView animateWithDuration:0.08
delay:0
options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseOut
animations:^{
if (!hasIcon && !self.normalImageView.hidden) {
self.normalImageView.backgroundColor = highlighted ? highlightBgColor : normalBgColor;
}
2025-11-20 20:36:31 +08:00
self.transform = CGAffineTransformMakeScale(scale, scale);
}
completion:nil];
2025-11-20 21:11:27 +08:00
// //
UIView *container = self.kb_keyboardContainer;
if ([container respondsToSelector:@selector(showPreviewForButton:)] &&
[container respondsToSelector:@selector(hidePreview)]) {
if (highlighted) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[container performSelector:@selector(showPreviewForButton:) withObject:self];
#pragma clang diagnostic pop
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[container performSelector:@selector(hidePreview)];
#pragma clang diagnostic pop
}
}
2025-10-28 20:11:40 +08:00
}
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
[self refreshStateAppearance];
}
- (void)refreshStateAppearance {
// Shift/CapsLock
2025-11-04 21:01:46 +08:00
KBSkinTheme *t = [KBSkinManager shared].current;
UIColor *base = nil;
2025-10-28 20:11:40 +08:00
if (self.isSelected) {
base = t.keyHighlightBackground ?: t.keyBackground;
2025-10-28 20:11:40 +08:00
} else {
base = t.keyBackground;
2025-10-28 20:11:40 +08:00
}
if (!base) {
base = [UIColor whiteColor];
}
self.baseBackgroundColor = base;
// normalImageView
self.backgroundColor = [UIColor clearColor];
// icon
if (self.iconView.image != nil || self.normalImageView.hidden) {
return;
}
self.normalImageView.backgroundColor = base;
2025-10-28 10:18:10 +08:00
}
2025-11-18 20:53:47 +08:00
- (void)applyThemeForCurrentKey {
//
// - identifier: letter_q
// - caseVariant: 0/1/2 => //
NSString *identifier = self.key.identifier;
2025-11-18 20:53:47 +08:00
NSInteger variant = (NSInteger)self.key.caseVariant;
2025-12-16 20:20:57 +08:00
KBSkinManager *skinManager = [KBSkinManager shared];
UIImage *iconImg = [skinManager iconImageForKeyIdentifier:identifier caseVariant:variant];
if (!iconImg && [identifier isEqualToString:@"ai"]) {
NSString *skinId = skinManager.current.skinId ?: @"";
BOOL usingDefaultSkin = (skinId.length == 0 || [skinId isEqualToString:@"default"]);
if (usingDefaultSkin) {
iconImg = [UIImage imageNamed:@"ai_key_icon"];
}
}
//
2025-11-18 20:53:47 +08:00
self.iconView.image = iconImg;
self.iconView.hidden = (iconImg == nil);
BOOL hasIcon = (iconImg != nil);
self.normalImageView.hidden = hasIcon;
if (hasIcon) {
//
[self setTitle:@"" forState:UIControlStateNormal];
[self setTitle:@"" forState:UIControlStateHighlighted];
[self setTitle:@"" forState:UIControlStateSelected];
self.titleLabel.hidden = YES;
self.normalImageView.backgroundColor = [UIColor clearColor];
} else {
// 使 key.title hidden_keys
[self setTitle:self.key.title forState:UIControlStateNormal];
BOOL hideTextBySkin = [[KBSkinManager shared] shouldHideKeyTextForIdentifier:identifier];
self.titleLabel.hidden = hideTextBySkin;
}
2025-11-18 20:53:47 +08:00
}
- (UIImageView *)normalImageView{
if (!_normalImageView) {
_normalImageView = [[UIImageView alloc] init];
// refreshStateAppearance /
_normalImageView.backgroundColor = [UIColor whiteColor];
_normalImageView.layer.cornerRadius = 6;
_normalImageView.layer.masksToBounds = true;
}
return _normalImageView;
}
///
- (UIColor *)kb_darkerColorForColor:(UIColor *)color {
if (!color) return [UIColor colorWithWhite:0.9 alpha:1.0];
CGFloat h = 0, s = 0, b = 0, a = 0;
if ([color getHue:&h saturation:&s brightness:&b alpha:&a]) {
return [UIColor colorWithHue:h saturation:s brightness:MAX(b * 0.9, 0.0) alpha:a];
}
CGFloat white = 0;
if ([color getWhite:&white alpha:&a]) {
return [UIColor colorWithWhite:MAX(white * 0.9, 0.0) alpha:a];
}
return color;
}
2025-10-28 10:18:10 +08:00
@end
2025-11-20 21:11:27 +08:00
@implementation KBKeyButton (KBKeyboardContainer)
- (UIView *)kb_keyboardContainer {
UIView *v = self.superview;
while (v) {
// KBKeyboardView
if ([NSStringFromClass(v.class) isEqualToString:@"KBKeyboardView"]) {
return v;
}
v = v.superview;
}
return nil;
}
@end