This commit is contained in:
2025-11-03 16:57:24 +08:00
parent 1673a2f4be
commit 915b329805
7 changed files with 187 additions and 98 deletions

View File

@@ -12,7 +12,9 @@
"home_title" = "Home"; "home_title" = "Home";
"home_input_placeholder" = "Type here to test the keyboard"; "home_input_placeholder" = "Type here to test the keyboard";
"home_item_lang_test" = "Language Test"; "home_item_lang_test" = "Language Test";
"home_item_keyboard_permission" = "Keyboard Permission Guide";
"lang_test_title" = "Language Test"; "lang_test_title" = "Language Test";
"lang_toggle" = "Toggle Language"; "lang_toggle" = "Toggle Language";
"current_lang" = "Current: %@"; "current_lang" = "Current: %@";
"common_back" = "Back";

View File

@@ -12,7 +12,9 @@
"home_title" = "首页"; "home_title" = "首页";
"home_input_placeholder" = "在此输入,测试键盘"; "home_input_placeholder" = "在此输入,测试键盘";
"home_item_lang_test" = "多语言测试"; "home_item_lang_test" = "多语言测试";
"home_item_keyboard_permission" = "键盘权限引导";
"lang_test_title" = "多语言测试"; "lang_test_title" = "多语言测试";
"lang_toggle" = "切换语言"; "lang_toggle" = "切换语言";
"current_lang" = "当前:%@"; "current_lang" = "当前:%@";
"common_back" = "返回";

View File

@@ -35,35 +35,11 @@ static NSString * const kKBKeyboardExtensionBundleId = @"com.keyBoardst.CustomKe
/// GroupID /// GroupID
// buglyConfig.applicationGroupIdentifier = @""; // buglyConfig.applicationGroupIdentifier = @"";
[Bugly startWithAppId:BuglyId config:buglyConfig]; [Bugly startWithAppId:BuglyId config:buglyConfig];
/// // KBGuideVC
dispatch_async(dispatch_get_main_queue(), ^{
UIViewController *top = [UIViewController kb_topMostViewController];
if (top) {
Class mgrCls = NSClassFromString(@"KBKeyboardPermissionManager");
if (mgrCls && [mgrCls respondsToSelector:@selector(shared)]) {
id mgr = [mgrCls performSelector:@selector(shared)];
if ([mgr respondsToSelector:@selector(presentPermissionIfNeededFrom:)]) {
// API
void (*func)(id, SEL, UIViewController *) = (void (*)(id, SEL, UIViewController *))objc_msgSend;
func(mgr, @selector(presentPermissionIfNeededFrom:), top);
}
} else {
//
[self kb_presentPermissionIfNeeded];
}
}
});
return YES; return YES;
} }
- (void)applicationDidBecomeActive:(UIApplication *)application{ - (void)applicationDidBecomeActive:(UIApplication *)application{}
// When returning from Settings, re-check the keyboard enable state
// and hide the guide if the user has enabled our keyboard.
// Also shows the guide again if still not enabled.
dispatch_async(dispatch_get_main_queue(), ^{
[self kb_presentPermissionIfNeeded];
});
}
- (void)setupRootVC{ - (void)setupRootVC{
@@ -120,20 +96,7 @@ static NSString * const kKBKeyboardExtensionBundleId = @"com.keyBoardst.CustomKe
- (void)kb_presentPermissionIfNeeded - (void)kb_presentPermissionIfNeeded
{ {
BOOL enabled = KBIsKeyboardEnabled(); // KBGuideVC
UIViewController *top = [UIViewController kb_topMostViewController];
if (!top) return;
if ([top isKindOfClass:[KBPermissionViewController class]]) {
if (enabled) {
[top dismissViewControllerAnimated:YES completion:nil];
}
return;
}
if (!enabled) {
KBPermissionViewController *guide = [KBPermissionViewController new];
guide.modalPresentationStyle = UIModalPresentationFullScreen;
[top presentViewController:guide animated:YES completion:nil];
}
} }

View File

@@ -9,6 +9,8 @@
#import "KBGuideTopCell.h" #import "KBGuideTopCell.h"
#import "KBGuideKFCell.h" #import "KBGuideKFCell.h"
#import "KBGuideUserCell.h" #import "KBGuideUserCell.h"
#import "KBPermissionViewController.h"
#import "KBKeyboardPermissionManager.h"
typedef NS_ENUM(NSInteger, KBGuideItemType) { typedef NS_ENUM(NSInteger, KBGuideItemType) {
KBGuideItemTypeTop = 0, // KBGuideItemTypeTop = 0, //
@@ -75,12 +77,49 @@ typedef NS_ENUM(NSInteger, KBGuideItemType) {
self.bgTap.cancelsTouchesInView = NO; self.bgTap.cancelsTouchesInView = NO;
self.bgTap.delegate = self; self.bgTap.delegate = self;
[self.tableView addGestureRecognizer:self.bgTap]; [self.tableView addGestureRecognizer:self.bgTap];
// /
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kb_checkKeyboardPermission) name:UIApplicationDidBecomeActiveNotification object:nil];
} }
- (void)dealloc { - (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self]; [[NSNotificationCenter defaultCenter] removeObserver:self];
} }
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
//
[self kb_checkKeyboardPermission];
}
///
/// - 访 =>
/// - =>
- (void)kb_checkKeyboardPermission {
KBKeyboardPermissionManager *mgr = [KBKeyboardPermissionManager shared];
BOOL enabled = [mgr isKeyboardEnabled];
KBFARecord fa = [mgr lastKnownFullAccess];
BOOL needGuide = (!enabled) || (enabled && fa == KBFARecordDenied);
UIViewController *top = [UIViewController kb_topMostViewController];
if (needGuide) {
if (![top isKindOfClass:[KBPermissionViewController class]]) {
KBPermissionViewController *guide = [KBPermissionViewController new];
guide.modalPresentationStyle = UIModalPresentationFullScreen;
__weak typeof(self) weakSelf = self;
guide.onBack = ^{
// 退
[weakSelf.navigationController popViewControllerAnimated:YES];
};
[top presentViewController:guide animated:YES completion:nil];
}
} else {
if ([top isKindOfClass:[KBPermissionViewController class]]) {
[top dismissViewControllerAnimated:YES completion:nil];
}
}
}
- (void)kb_didTapBackground { - (void)kb_didTapBackground {
// //
[self.view endEditing:YES]; [self.view endEditing:YES];

View File

@@ -39,8 +39,8 @@
self.tableView.tableHeaderView = header; self.tableView.tableHeaderView = header;
[self.view addSubview:self.tableView]; [self.view addSubview:self.tableView];
// //
self.items = @[ KBLocalized(@"home_item_lang_test") ]; self.items = @[ KBLocalized(@"home_item_lang_test"), KBLocalized(@"home_item_keyboard_permission") ];
// 便 // 便
dispatch_async(dispatch_get_main_queue(), ^{ [self.textView becomeFirstResponder]; }); dispatch_async(dispatch_get_main_queue(), ^{ [self.textView becomeFirstResponder]; });
@@ -56,7 +56,7 @@
// //
self.title = KBLocalized(@"home_title"); self.title = KBLocalized(@"home_title");
// items cell // items cell
self.items = @[ KBLocalized(@"home_item_lang_test") ]; self.items = @[ KBLocalized(@"home_item_lang_test"), KBLocalized(@"home_item_keyboard_permission") ];
[self.tableView reloadData]; [self.tableView reloadData];
} }
@@ -87,6 +87,10 @@
// //
KBLangTestVC *vc = [KBLangTestVC new]; KBLangTestVC *vc = [KBLangTestVC new];
[self.navigationController pushViewController:vc animated:YES]; [self.navigationController pushViewController:vc animated:YES];
} else if (indexPath.row == 1) {
//
KBGuideVC *vc = [KBGuideVC new];
[self.navigationController pushViewController:vc animated:YES];
} }
} }

View File

@@ -11,6 +11,9 @@ NS_ASSUME_NONNULL_BEGIN
@interface KBPermissionViewController : UIViewController @interface KBPermissionViewController : UIViewController
/// 点击页面左上角“返回”时回调。用于让调用方(如 KBGuideVC一起退出等自定义行为。
@property (nonatomic, copy, nullable) void (^onBack)(void);
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

View File

@@ -9,7 +9,12 @@
#import <TargetConditionals.h> #import <TargetConditionals.h>
@interface KBPermissionViewController () @interface KBPermissionViewController ()
@property (nonatomic, strong) UIButton *backButton; //
@property (nonatomic, strong) UILabel *titleLabel; //
@property (nonatomic, strong) UILabel *tipsLabel; //
@property (nonatomic, strong) UIView *cardView; //
@property (nonatomic, strong) UIButton *openButton; //
@property (nonatomic, strong) UILabel *helpLabel; //
@end @end
@implementation KBPermissionViewController @implementation KBPermissionViewController
@@ -18,67 +23,66 @@
[super viewDidLoad]; [super viewDidLoad];
self.view.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0]; self.view.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0];
UIButton *close = [UIButton buttonWithType:UIButtonTypeSystem]; // +
[close setTitle:@"X" forState:UIControlStateNormal]; [self.view addSubview:self.backButton];
close.titleLabel.font = [UIFont systemFontOfSize:20 weight:UIFontWeightSemibold]; [self.view addSubview:self.titleLabel];
close.tintColor = [UIColor darkTextColor]; [self.view addSubview:self.tipsLabel];
close.frame = CGRectMake(self.view.bounds.size.width - 44, 44, 28, 28); [self.view addSubview:self.cardView];
close.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin; [self.view addSubview:self.openButton];
[close addTarget:self action:@selector(dismissSelf) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:self.helpLabel];
[self.view addSubview:close];
UILabel *title = [[UILabel alloc] init]; // Masonry
title.text = [[KBLocalizationManager shared] localizedStringForKey:@"perm_title_enable" table:nil value:@"启用输入法"]; [self.backButton mas_makeConstraints:^(MASConstraintMaker *make) {
title.font = [UIFont systemFontOfSize:22 weight:UIFontWeightSemibold]; make.left.equalTo(self.view).offset(16);
title.textColor = [UIColor blackColor]; make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(8);
title.textAlignment = NSTextAlignmentCenter;
title.frame = CGRectMake(24, 100, self.view.bounds.size.width - 48, 28); make.width.mas_equalTo(60);
title.autoresizingMask = UIViewAutoresizingFlexibleWidth; make.height.mas_equalTo(32);
[self.view addSubview:title]; }];
UILabel *tips = [[UILabel alloc] init]; [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
// Localizable.strings make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(48);
tips.text = [[KBLocalizationManager shared] localizedStringForKey:@"perm_steps" table:nil value:@"1 开启键盘 > 2 允许完全访问"];
tips.font = [UIFont systemFontOfSize:14]; make.left.equalTo(self.view).offset(24);
tips.textColor = [UIColor darkGrayColor]; make.right.equalTo(self.view).offset(-24);
tips.textAlignment = NSTextAlignmentCenter; make.height.mas_equalTo(28);
tips.frame = CGRectMake(24, CGRectGetMaxY(title.frame) + 8, self.view.bounds.size.width - 48, 20); }];
tips.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self.view addSubview:tips];
UIView *card = [[UIView alloc] initWithFrame:CGRectMake(32, CGRectGetMaxY(tips.frame) + 28, self.view.bounds.size.width - 64, 260)]; [self.tipsLabel mas_makeConstraints:^(MASConstraintMaker *make) {
card.backgroundColor = [UIColor whiteColor]; make.top.equalTo(self.titleLabel.mas_bottom).offset(8);
card.layer.cornerRadius = 16; make.left.equalTo(self.view).offset(24);
card.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.1].CGColor; make.right.equalTo(self.view).offset(-24);
card.layer.shadowOpacity = 1; }];
card.layer.shadowRadius = 12;
[self.view addSubview:card];
UIButton *open = [UIButton buttonWithType:UIButtonTypeSystem]; [self.cardView mas_makeConstraints:^(MASConstraintMaker *make) {
[open setTitle:[[KBLocalizationManager shared] localizedStringForKey:@"perm_open_settings" table:nil value:@"去设置中开启"] forState:UIControlStateNormal]; make.top.equalTo(self.tipsLabel.mas_bottom).offset(28);
open.titleLabel.font = [UIFont systemFontOfSize:17 weight:UIFontWeightSemibold]; make.left.equalTo(self.view).offset(32);
[open setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; make.right.equalTo(self.view).offset(-32);
open.backgroundColor = [UIColor colorWithRed:0.22 green:0.49 blue:0.96 alpha:1.0]; make.height.mas_equalTo(260);
open.layer.cornerRadius = 8; }];
CGFloat btnW = self.view.bounds.size.width - 64;
open.frame = CGRectMake(32, CGRectGetMaxY(card.frame) + 32, btnW, 48);
open.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
[open addTarget:self action:@selector(openSettings) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:open];
UILabel *help = [[UILabel alloc] init]; [self.openButton mas_makeConstraints:^(MASConstraintMaker *make) {
help.text = [[KBLocalizationManager shared] localizedStringForKey:@"perm_help" table:nil value:@"没有找到键盘? 请前往 设置 > 通用 > 键盘 > 键盘 > 添加新键盘"]; make.top.equalTo(self.cardView.mas_bottom).offset(32);
help.font = [UIFont systemFontOfSize:12]; make.left.equalTo(self.view).offset(32);
help.textColor = [UIColor grayColor]; make.right.equalTo(self.view).offset(-32);
help.textAlignment = NSTextAlignmentCenter; make.height.mas_equalTo(48);
help.numberOfLines = 2; }];
help.frame = CGRectMake(24, CGRectGetMaxY(open.frame) + 12, self.view.bounds.size.width - 48, 36);
help.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; [self.helpLabel mas_makeConstraints:^(MASConstraintMaker *make) {
[self.view addSubview:help]; make.top.equalTo(self.openButton.mas_bottom).offset(12);
make.left.equalTo(self.view).offset(24);
make.right.equalTo(self.view).offset(-24);
}];
} }
- (void)dismissSelf { #pragma mark - Actions
[self dismissViewControllerAnimated:YES completion:nil];
- (void)onBack {
// 退
void (^handler)(void) = self.onBack;
[self dismissViewControllerAnimated:YES completion:^{
if (handler) handler();
}];
} }
- (void)openSettings { - (void)openSettings {
@@ -93,4 +97,76 @@
} }
} }
#pragma mark - Lazy Subviews
- (UIButton *)backButton {
if (!_backButton) {
_backButton = [UIButton buttonWithType:UIButtonTypeSystem];
[_backButton setTitle:KBLocalized(@"common_back") forState:UIControlStateNormal];
_backButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium];
[_backButton setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal];
[_backButton addTarget:self action:@selector(onBack) forControlEvents:UIControlEventTouchUpInside];
}
return _backButton;
}
- (UILabel *)titleLabel {
if (!_titleLabel) {
_titleLabel = [UILabel new];
_titleLabel.text = KBLocalized(@"perm_title_enable");
_titleLabel.font = [UIFont systemFontOfSize:22 weight:UIFontWeightSemibold];
_titleLabel.textColor = [UIColor blackColor];
_titleLabel.textAlignment = NSTextAlignmentCenter;
}
return _titleLabel;
}
- (UILabel *)tipsLabel {
if (!_tipsLabel) {
_tipsLabel = [UILabel new];
_tipsLabel.text = KBLocalized(@"perm_steps");
_tipsLabel.font = [UIFont systemFontOfSize:14];
_tipsLabel.textColor = [UIColor darkGrayColor];
_tipsLabel.textAlignment = NSTextAlignmentCenter;
}
return _tipsLabel;
}
- (UIView *)cardView {
if (!_cardView) {
_cardView = [UIView new];
_cardView.backgroundColor = [UIColor whiteColor];
_cardView.layer.cornerRadius = 16;
_cardView.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.1].CGColor;
_cardView.layer.shadowOpacity = 1;
_cardView.layer.shadowRadius = 12;
}
return _cardView;
}
- (UIButton *)openButton {
if (!_openButton) {
_openButton = [UIButton buttonWithType:UIButtonTypeSystem];
[_openButton setTitle:KBLocalized(@"perm_open_settings") forState:UIControlStateNormal];
_openButton.titleLabel.font = [UIFont systemFontOfSize:17 weight:UIFontWeightSemibold];
[_openButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
_openButton.backgroundColor = [UIColor colorWithRed:0.22 green:0.49 blue:0.96 alpha:1.0];
_openButton.layer.cornerRadius = 8;
[_openButton addTarget:self action:@selector(openSettings) forControlEvents:UIControlEventTouchUpInside];
}
return _openButton;
}
- (UILabel *)helpLabel {
if (!_helpLabel) {
_helpLabel = [UILabel new];
_helpLabel.text = KBLocalized(@"perm_help");
_helpLabel.font = [UIFont systemFontOfSize:12];
_helpLabel.textColor = [UIColor grayColor];
_helpLabel.textAlignment = NSTextAlignmentCenter;
_helpLabel.numberOfLines = 2;
}
return _helpLabel;
}
@end @end