添加guard 蒙层

This commit is contained in:
2025-11-27 15:34:33 +08:00
parent 2435d760e8
commit 2760a070a3
8 changed files with 270 additions and 11 deletions

View File

@@ -83,6 +83,11 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
// NSLog(@"[Keyboard] 读取到的数据: %@", value);
}
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[[KBLocalizationManager shared] reloadFromSharedStorageIfNeeded];
}
- (void)setupUI {
self.view.translatesAutoresizingMaskIntoConstraints = NO;

View File

@@ -47,6 +47,8 @@ extern NSString * const KBLocalizationDidChangeNotification;
/// 基于一组“偏好语言”计算最佳支持语言。
- (NSString *)bestSupportedLanguageForPreferred:(NSArray<NSString *> *)preferred;
- (void)reloadFromSharedStorageIfNeeded;
@end
/// 便捷宏:与 NSLocalizedString 类似,但遵循 KBLocalizationManager 当前语言

View File

@@ -177,4 +177,14 @@ static inline NSMutableDictionary *KBLocBaseKCQuery(void) {
return lang;
}
- (void)reloadFromSharedStorageIfNeeded {
NSString *saved = [[self class] kc_read];
if (saved.length == 0) return;
if ([saved isEqualToString:self.currentLanguageCode]) return;
[self applyLanguage:saved];
[[NSNotificationCenter defaultCenter] postNotificationName:KBLocalizationDidChangeNotification
object:nil];
}
@end

View File

@@ -54,6 +54,8 @@
04791FF72ED5B985004E8522 /* Christmas.zip in Resources */ = {isa = PBXBuildFile; fileRef = 04791FF62ED5B985004E8522 /* Christmas.zip */; };
04791FFB2ED5EAB8004E8522 /* fense.zip in Resources */ = {isa = PBXBuildFile; fileRef = 04791FFA2ED5EAB8004E8522 /* fense.zip */; };
04791FFC2ED71D17004E8522 /* UIColor+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95E42EB220B5007BD342 /* UIColor+Extension.m */; };
04791FFF2ED830FA004E8522 /* KBKeyboardMaskView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04791FFE2ED830FA004E8522 /* KBKeyboardMaskView.m */; };
047920032ED8343D004E8522 /* kb_guide_keyboard.gif in Resources */ = {isa = PBXBuildFile; fileRef = 047920022ED8343D004E8522 /* kb_guide_keyboard.gif */; };
047C650D2EBC8A840035E841 /* KBPanModalView.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C650C2EBC8A840035E841 /* KBPanModalView.m */; };
047C65102EBCA8DD0035E841 /* HomeRankContentVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C650F2EBCA8DD0035E841 /* HomeRankContentVC.m */; };
047C65502EBCBA9E0035E841 /* KBShopVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C654F2EBCBA9E0035E841 /* KBShopVC.m */; };
@@ -265,6 +267,9 @@
04791F972ED49CE7004E8522 /* KBFont.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFont.m; sourceTree = "<group>"; };
04791FF62ED5B985004E8522 /* Christmas.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = Christmas.zip; sourceTree = "<group>"; };
04791FFA2ED5EAB8004E8522 /* fense.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = fense.zip; sourceTree = "<group>"; };
04791FFD2ED830FA004E8522 /* KBKeyboardMaskView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBKeyboardMaskView.h; sourceTree = "<group>"; };
04791FFE2ED830FA004E8522 /* KBKeyboardMaskView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBKeyboardMaskView.m; sourceTree = "<group>"; };
047920022ED8343D004E8522 /* kb_guide_keyboard.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = kb_guide_keyboard.gif; sourceTree = "<group>"; };
047C650B2EBC8A840035E841 /* KBPanModalView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBPanModalView.h; sourceTree = "<group>"; };
047C650C2EBC8A840035E841 /* KBPanModalView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBPanModalView.m; sourceTree = "<group>"; };
047C650E2EBCA8DD0035E841 /* HomeRankContentVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeRankContentVC.h; sourceTree = "<group>"; };
@@ -619,17 +624,10 @@
path = FunctionTest;
sourceTree = "<group>";
};
047C652B2EBCAAAC0035E841 /* Images */ = {
isa = PBXGroup;
children = (
);
path = Images;
sourceTree = "<group>";
};
047C652C2EBCAAAC0035E841 /* Resource */ = {
isa = PBXGroup;
children = (
047C652B2EBCAAAC0035E841 /* Images */,
047920022ED8343D004E8522 /* kb_guide_keyboard.gif */,
04286A122ECDEBF900CE730C /* KBSkinIconMap.strings */,
04286A0E2ECDA71B00CE730C /* 001.zip */,
);
@@ -1171,6 +1169,8 @@
04FC97022EB30A00007BD342 /* KBGuideKFCell.m */,
04FC97042EB30A00007BD342 /* KBGuideUserCell.h */,
04FC97052EB30A00007BD342 /* KBGuideUserCell.m */,
04791FFD2ED830FA004E8522 /* KBKeyboardMaskView.h */,
04791FFE2ED830FA004E8522 /* KBKeyboardMaskView.m */,
);
path = V;
sourceTree = "<group>";
@@ -1466,6 +1466,7 @@
04286A0F2ECDA71B00CE730C /* 001.zip in Resources */,
04C6EABA2EAF86530089C901 /* Assets.xcassets in Resources */,
04A9FE212EB893F10020DB6D /* Localizable.strings in Resources */,
047920032ED8343D004E8522 /* kb_guide_keyboard.gif in Resources */,
04C6EABC2EAF86530089C901 /* LaunchScreen.storyboard in Resources */,
04286A132ECDEBF900CE730C /* KBSkinIconMap.strings in Resources */,
04C6EABD2EAF86530089C901 /* Main.storyboard in Resources */,
@@ -1608,6 +1609,7 @@
049FB20E2EC1CD2800FAB05D /* KBAlert.m in Sources */,
04A9FE162EB873C80020DB6D /* UIViewController+Extension.m in Sources */,
04C6EABE2EAF86530089C901 /* AppDelegate.m in Sources */,
04791FFF2ED830FA004E8522 /* KBKeyboardMaskView.m in Sources */,
04FC95F12EB339A7007BD342 /* LoginViewController.m in Sources */,
048908E92EBF843000FABA60 /* KBSkinDetailHeaderCell.m in Sources */,
04FC96142EB34E00007BD342 /* KBLoginSheetViewController.m in Sources */,

View File

@@ -0,0 +1,29 @@
//
// KBKeyboardMaskView.h
// keyBoard
//
// Created by Mac on 2025/11/27.
//
#import <UIKit/UIKit.h>
#import <FLAnimatedImage/FLAnimatedImage.h>
NS_ASSUME_NONNULL_BEGIN
/// 覆盖在 KBGuideVC 上方的“请选择自家键盘”蒙层
/// - 左上角:返回箭头
/// - 中间:播放 GIF 的区域(宽=屏幕宽,高=300
/// - 点击任意空白区域:回调给外部(用于激活输入框)
@interface KBKeyboardMaskView : UIView
@property (nonatomic, strong, readonly) UIButton *backButton;
@property (nonatomic, strong, readonly) FLAnimatedImageView *gifView;
/// 点击蒙层空白时回调(不包括 backButton
@property (nonatomic, copy) void (^tapHandler)(void);
/// 更新内部 GIF 与键盘的相对位置,保证不被遮挡
- (void)updateForKeyboardHeight:(CGFloat)kbHeight
duration:(NSTimeInterval)duration
curve:(UIViewAnimationOptions)curve;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,125 @@
//
// KBKeyboardMaskView.m
// keyBoard
//
// Created by Mac on 2025/11/27.
//
#import "KBKeyboardMaskView.h"
@interface KBKeyboardMaskView ()
@property (nonatomic, strong) UIButton *backButton;
@property (nonatomic, strong) FLAnimatedImageView *gifView;
@property (nonatomic, assign) CGFloat keyboardHeight;
@end
@implementation KBKeyboardMaskView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (!self) return nil;
self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.55];
self.userInteractionEnabled = YES;
//
_backButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *backImg = [UIImage imageNamed:@"close_white2_icon"];
[_backButton setImage:backImg forState:UIControlStateNormal];
[self addSubview:_backButton];
[_backButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self).offset(9);
if (@available(iOS 11.0, *)) {
make.top.equalTo(self.mas_safeAreaLayoutGuideTop).offset(4);
} else {
make.top.equalTo(self).offset(40);
}
make.width.height.mas_equalTo(40);
}];
// GIF
_gifView = [FLAnimatedImageView new];
_gifView.contentMode = UIViewContentModeScaleAspectFit;
_gifView.clipsToBounds = YES;
[self addSubview:_gifView];
// ==300 layoutSubviews
CGFloat screenW = UIScreen.mainScreen.bounds.size.width;
[_gifView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self);
make.width.mas_equalTo(screenW);
make.height.mas_equalTo(300);
// layoutSubviews
}];
//
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapMask:)];
[self addGestureRecognizer:tap];
// GIF
NSString *gifPath = [[NSBundle mainBundle] pathForResource:@"kb_guide_keyboard" ofType:@"gif"];
if (gifPath.length > 0) {
NSData *data = [NSData dataWithContentsOfFile:gifPath];
if (data.length > 0) {
FLAnimatedImage *img = [FLAnimatedImage animatedImageWithGIFData:data];
_gifView.animatedImage = img;
}
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
// GIF
// -
// - 20pt safe
CGFloat viewH = CGRectGetHeight(self.bounds);
CGFloat gifH = 300.0;
CGFloat topMargin = 80.0; //
CGFloat bottomMargin = 20.0;
CGFloat y = 0;
if (self.keyboardHeight <= 0) {
//
y = (viewH - gifH) * 0.5;
if (y < topMargin) y = topMargin;
} else {
CGFloat maxBottom = viewH - self.keyboardHeight - bottomMargin;
y = maxBottom - gifH;
if (y < topMargin) y = topMargin;
}
CGRect frame = self.gifView.frame;
frame.origin.y = y;
self.gifView.frame = frame;
}
- (void)onTapMask:(UITapGestureRecognizer *)gr {
CGPoint p = [gr locationInView:self];
// tapHandler
if (CGRectContainsPoint(self.backButton.frame, p)) {
return;
}
if (self.tapHandler) {
self.tapHandler();
}
}
- (void)updateForKeyboardHeight:(CGFloat)kbHeight
duration:(NSTimeInterval)duration
curve:(UIViewAnimationOptions)curve {
self.keyboardHeight = MAX(kbHeight, 0);
// 便 layoutSubviews gifView Y
[self setNeedsLayout];
[UIView animateWithDuration:duration
delay:0
options:curve
animations:^{
[self layoutIfNeeded];
}
completion:nil];
}
@end

View File

@@ -11,6 +11,7 @@
#import "KBGuideUserCell.h"
#import "KBPermissionViewController.h"
#import "KBKeyboardPermissionManager.h"
#import "KBKeyboardMaskView.h"
typedef NS_ENUM(NSInteger, KBGuideItemType) {
KBGuideItemTypeTop = 0, //
@@ -32,6 +33,12 @@ typedef NS_ENUM(NSInteger, KBGuideItemType) {
///
@property (nonatomic, copy, nullable) NSString *kb_lastInputModeIdentifier;
/// + GIF
@property (nonatomic, strong, nullable) KBKeyboardMaskView *kbKeyboardMaskView;
/// GIF
@property (nonatomic, assign) CGFloat kb_currentKeyboardHeight;
@end
@implementation KBGuideVC
@@ -94,8 +101,7 @@ typedef NS_ENUM(NSInteger, KBGuideItemType) {
//
[self kb_preparePermissionOverlayIfNeeded];
}
- (void)dealloc {
@@ -194,6 +200,7 @@ typedef NS_ENUM(NSInteger, KBGuideItemType) {
CGRect endFrame = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat screenH = UIScreen.mainScreen.bounds.size.height;
CGFloat kbHeight = MAX(0, screenH - endFrame.origin.y);
self.kb_currentKeyboardHeight = kbHeight;
CGFloat safeBtm = 0;
if (@available(iOS 11.0, *)) { safeBtm = self.view.safeAreaInsets.bottom; }
@@ -212,6 +219,13 @@ typedef NS_ENUM(NSInteger, KBGuideItemType) {
//
[self kb_evaluateCurrentInputModeAndNotifyIfNeeded];
}];
// GIF
if (self.kbKeyboardMaskView) {
[self.kbKeyboardMaskView updateForKeyboardHeight:kbHeight
duration:duration
curve:curve];
}
}
- (void)scrollToBottomAnimated:(BOOL)animated {
@@ -272,7 +286,9 @@ typedef NS_ENUM(NSInteger, KBGuideItemType) {
self.kb_lastInputModeIdentifier = currId;
BOOL isMine = [currId rangeOfString:KB_KEYBOARD_EXTENSION_BUNDLE_ID].location != NSNotFound;
[KBHUD showInfo:(isMine ? KBLocalized(@"是自己的键盘") : KBLocalized(@"❎不是自己的键盘"))];
// /
[self kb_updateKeyboardMaskForIsMyKeyboard:isMine];
}
///
@@ -290,6 +306,76 @@ typedef NS_ENUM(NSInteger, KBGuideItemType) {
});
}
/// /
- (void)kb_updateKeyboardMaskForIsMyKeyboard:(BOOL)isMine {
//
if (self.permVC && self.permVC.view.hidden == NO) {
if (self.kbKeyboardMaskView) {
self.kbKeyboardMaskView.hidden = YES;
}
return;
}
BOOL shouldShow = !isMine;
if (shouldShow) {
//
if (!self.kbKeyboardMaskView) {
KBKeyboardMaskView *mask = [[KBKeyboardMaskView alloc] initWithFrame:self.view.bounds];
__weak typeof(self) weakSelf = self;
mask.tapHandler = ^{
__strong typeof(weakSelf) self = weakSelf;
if (!self) return;
// / textField
if ([self.textField isFirstResponder]) {
// ->
[self.view endEditing:YES];
} else {
// ->
[self.textField becomeFirstResponder];
}
};
// 退 KBGuideVC
[mask.backButton addTarget:self action:@selector(kb_onMaskBack) forControlEvents:UIControlEventTouchUpInside];
self.kbKeyboardMaskView = mask;
if (self.permVC && self.permVC.view.superview == self.view) {
//
[self.view insertSubview:mask belowSubview:self.permVC.view];
} else {
[self.view addSubview:mask];
}
[mask mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
// GIF
[mask updateForKeyboardHeight:self.kb_currentKeyboardHeight
duration:0
curve:UIViewAnimationOptionCurveEaseInOut];
}
}
if (!self.kbKeyboardMaskView) return;
BOOL currentlyVisible = !self.kbKeyboardMaskView.hidden && self.kbKeyboardMaskView.alpha > 0.01;
if (shouldShow == currentlyVisible) return;
self.kbKeyboardMaskView.hidden = NO;
CGFloat targetAlpha = shouldShow ? 1.0 : 0.0;
[UIView animateWithDuration:0.25 animations:^{
self.kbKeyboardMaskView.alpha = targetAlpha;
} completion:^(BOOL finished) {
self.kbKeyboardMaskView.hidden = !shouldShow;
}];
}
/// KBGuideVC 退
- (void)kb_onMaskBack {
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - UITableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 KiB