添加按钮文字预览提示

This commit is contained in:
2025-11-20 21:11:27 +08:00
parent 6bdd111a3a
commit faa05e2a10
6 changed files with 168 additions and 3 deletions

View File

@@ -10,6 +10,7 @@
@interface KBKeyButton : UIButton
@property (nonatomic, strong) KBKey *key;
@property (nonatomic, strong) UIImageView *iconView;
/// 配置基础样式(背景、圆角等)。创建按钮时调用。
- (void)applyDefaultStyle;

View File

@@ -8,7 +8,8 @@
#import "KBSkinManager.h"
@interface KBKeyButton ()
@property (nonatomic, strong) UIImageView *iconView;
// 便 KBKeyboardView
@property (nonatomic, weak, readonly) UIView *kb_keyboardContainer;
@end
@implementation KBKeyButton
@@ -63,10 +64,8 @@
- (void)setHighlighted:(BOOL)highlighted {
[super setHighlighted:highlighted];
//
//
NSLog(@"来了老弟=====");
CGFloat scale = highlighted ? 0.9 : 1.0; // 0.9~0.95
[UIView animateWithDuration:0.08
delay:0
@@ -75,6 +74,23 @@
self.transform = CGAffineTransformMakeScale(scale, scale);
}
completion:nil];
// //
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
}
}
}
- (void)setSelected:(BOOL)selected {
@@ -124,3 +140,19 @@
}
@end
@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

View File

@@ -0,0 +1,21 @@
//
// KBKeyPreviewView.h
// CustomKeyboard
//
#import <UIKit/UIKit.h>
@class KBKey;
NS_ASSUME_NONNULL_BEGIN
/// 按键按下时显示的气泡预览视图(类似系统键盘上方弹出的放大字母)。
@interface KBKeyPreviewView : UIView
/// 配置预览内容:字符与可选图标。
- (void)configureWithKey:(KBKey *)key icon:(nullable UIImage *)icon;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,56 @@
//
// KBKeyPreviewView.m
// CustomKeyboard
//
#import "KBKeyPreviewView.h"
#import "KBKey.h"
@interface KBKeyPreviewView ()
@property (nonatomic, strong) UILabel *label;
@property (nonatomic, strong) UIImageView *iconView;
@end
@implementation KBKeyPreviewView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor colorWithWhite:1 alpha:1.0];
self.layer.cornerRadius = 8.0;
self.layer.masksToBounds = YES;
self.layer.borderWidth = 0.5;
self.layer.borderColor = [UIColor colorWithWhite:0 alpha:0.15].CGColor;
self.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.3].CGColor;
self.layer.shadowOpacity = 0.6;
self.layer.shadowOffset = CGSizeMake(0, 2);
self.layer.shadowRadius = 4.0;
// _iconView = [[UIImageView alloc] initWithFrame:CGRectZero];
// _iconView.contentMode = UIViewContentModeScaleAspectFit;
// _iconView.translatesAutoresizingMaskIntoConstraints = NO;
// [self addSubview:_iconView];
_label = [[UILabel alloc] initWithFrame:CGRectZero];
_label.font = [UIFont systemFontOfSize:28 weight:UIFontWeightSemibold];
_label.textAlignment = NSTextAlignmentCenter;
_label.textColor = [UIColor blackColor];
_label.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_label];
// 使
[NSLayoutConstraint activateConstraints:@[
[_label.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:4],
[_label.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-4],
[_label.topAnchor constraintEqualToAnchor:self.topAnchor constant:2],
[_label.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-2],
]];
}
return self;
}
- (void)configureWithKey:(KBKey *)key icon:(UIImage *)icon {
NSString *text = key.output.length > 0 ? key.output : key.title;
self.label.text = text;
}
@end

View File

@@ -8,6 +8,7 @@
#import "KBKey.h"
#import "KBResponderUtils.h" //
#import "KBSkinManager.h"
#import "KBKeyPreviewView.h"
@interface KBKeyboardView ()
@property (nonatomic, strong) UIView *row1;
@@ -17,6 +18,7 @@
@property (nonatomic, strong) NSArray<NSArray<KBKey *> *> *keysForRows;
// 退使 NSTimer GCD
@property (nonatomic, assign) BOOL backspaceHoldActive;
@property (nonatomic, strong) KBKeyPreviewView *previewView;
@end
@implementation KBKeyboardView
@@ -463,6 +465,53 @@
}
}
//
- (void)showPreviewForButton:(KBKeyButton *)button {
KBKey *key = button.key;
if (key.type != KBKeyTypeCharacter) return;
if (!self.previewView) {
self.previewView = [[KBKeyPreviewView alloc] initWithFrame:CGRectZero];
self.previewView.hidden = YES;
[self addSubview:self.previewView];
}
[self.previewView configureWithKey:key icon:button.iconView.image];
//
CGRect btnFrameInSelf = [button convertRect:button.bounds toView:self];
CGFloat previewWidth = MAX(CGRectGetWidth(btnFrameInSelf) * 1.4, 42.0);
CGFloat previewHeight = CGRectGetHeight(btnFrameInSelf) * 1.2;
CGFloat centerX = CGRectGetMidX(btnFrameInSelf);
CGFloat centerY = CGRectGetMinY(btnFrameInSelf) - previewHeight * 0.6;
self.previewView.frame = CGRectMake(0, 0, previewWidth, previewHeight);
self.previewView.center = CGPointMake(centerX, centerY);
self.previewView.alpha = 0.0;
self.previewView.hidden = NO;
[UIView animateWithDuration:0.08
delay:0
options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseOut
animations:^{
self.previewView.alpha = 1.0;
}
completion:nil];
}
- (void)hidePreview {
if (!self.previewView || self.previewView.isHidden) return;
[UIView animateWithDuration:0.06
delay:0
options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn
animations:^{
self.previewView.alpha = 0.0;
}
completion:^(BOOL finished) {
self.previewView.hidden = YES;
}];
}
// 退使 NSTimer/DisplayLink
- (void)onBackspaceLongPress:(UILongPressGestureRecognizer *)gr {
switch (gr.state) {

View File

@@ -37,6 +37,7 @@
0459D1B72EBA287900F2D189 /* KBSkinManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0459D1B62EBA287900F2D189 /* KBSkinManager.m */; };
0459D1B82EBA287900F2D189 /* KBSkinManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0459D1B62EBA287900F2D189 /* KBSkinManager.m */; };
046131112ECF3A6E00A6FADF /* fense.zip in Resources */ = {isa = PBXBuildFile; fileRef = 046131102ECF3A6E00A6FADF /* fense.zip */; };
046131142ECF454500A6FADF /* KBKeyPreviewView.m in Sources */ = {isa = PBXBuildFile; fileRef = 046131132ECF454500A6FADF /* KBKeyPreviewView.m */; };
0477BD952EBAFF4E0055D639 /* KBURLOpenBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BD932EBAFF4E0055D639 /* KBURLOpenBridge.m */; };
0477BDF02EBB76E30055D639 /* HomeSheetVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDEF2EBB76E30055D639 /* HomeSheetVC.m */; };
0477BDF32EBB7B850055D639 /* KBDirectionIndicatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDF22EBB7B850055D639 /* KBDirectionIndicatorView.m */; };
@@ -230,6 +231,8 @@
0459D1B52EBA287900F2D189 /* KBSkinManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinManager.h; sourceTree = "<group>"; };
0459D1B62EBA287900F2D189 /* KBSkinManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinManager.m; sourceTree = "<group>"; };
046131102ECF3A6E00A6FADF /* fense.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = fense.zip; sourceTree = "<group>"; };
046131122ECF454500A6FADF /* KBKeyPreviewView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBKeyPreviewView.h; sourceTree = "<group>"; };
046131132ECF454500A6FADF /* KBKeyPreviewView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBKeyPreviewView.m; sourceTree = "<group>"; };
0477BD922EBAFF4E0055D639 /* KBURLOpenBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBURLOpenBridge.h; sourceTree = "<group>"; };
0477BD932EBAFF4E0055D639 /* KBURLOpenBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBURLOpenBridge.m; sourceTree = "<group>"; };
0477BDEE2EBB76E30055D639 /* HomeSheetVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeSheetVC.h; sourceTree = "<group>"; };
@@ -871,6 +874,8 @@
04FC95692EB05497007BD342 /* KBKeyButton.m */,
04FC956B2EB054B7007BD342 /* KBKeyboardView.h */,
04FC956C2EB054B7007BD342 /* KBKeyboardView.m */,
046131122ECF454500A6FADF /* KBKeyPreviewView.h */,
046131132ECF454500A6FADF /* KBKeyPreviewView.m */,
04FC95772EB09BC8007BD342 /* KBKeyBoardMainView.h */,
04FC95782EB09BC8007BD342 /* KBKeyBoardMainView.m */,
04FC956E2EB09516007BD342 /* KBFunctionView.h */,
@@ -1524,6 +1529,7 @@
04A9FE0F2EB481100020DB6D /* KBHUD.m in Sources */,
04C6EADD2EAF8CEB0089C901 /* KBToolBar.m in Sources */,
04FC95792EB09BC8007BD342 /* KBKeyBoardMainView.m in Sources */,
046131142ECF454500A6FADF /* KBKeyPreviewView.m in Sources */,
04FC95732EB09570007BD342 /* KBFunctionBarView.m in Sources */,
04C6EAD82EAF870B0089C901 /* KeyboardViewController.m in Sources */,
0459D1B82EBA287900F2D189 /* KBSkinManager.m in Sources */,