iOS - 隐藏在键盘下的 UIAlertController
iOS - UIAlertController hidden under keyboard
我有一个 UIAlertController
来自 UIViewController
的呈现,它作为最后一个 UIViewController
被推入 UINavigationController
。这个UIAlertViewController
里面有一个UITextField
。
我的问题是,当我 select 时,UITextField
键盘出现,但 UIAlertViewController
保持居中,部分隐藏在键盘下方。
我的代码如下所示:
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Enter Your PIN" message:@"Please enter your PIN!" preferredStyle:UIAlertControllerStyleAlert];
[alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
[textField setSecureTextEntry:YES];
}];
UIAlertAction* okAction = [UIAlertAction actionWithTitle:@"Confirm"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action) { }];
UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * _Nonnull action) {
}];
[alert addAction:okAction];
[alert addAction:cancelAction];
[self presentViewController:alert animated:YES completion:nil];
截图
应该是自动调整的。
检查您的视图层次结构
You can manage your keyboard based on textField location.
// Call this method somewhere in your view controller in **viewdidload** method
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
//Add in your View Controller which Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your app might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
[self.scrollView scrollRectToVisible:activeField.frame animated:YES];
}
}
// Add in your View Controller which Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
Initialize UITextField * activeField;
Additional methods for tracking the active text field.
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
activeField = nil;
}
你也可以在苹果文档中查看这些概念。
https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html
如果我理解你的话,问题是键盘下方显示了警报。我认为问题在于 UIAlertController 显示在您的 viewController 上?但是键盘是从 rootViewController 显示的。试试这个代码来解决问题
let alert = UIAlertController(title: "Title", message: NSLocalizedString("Message", comment: ""), preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default) { action in }
alert.addAction(okAction)
let rootViewController: UIViewController = UIApplication.shared.windows.last!.rootViewController!
rootViewController.present(alert, animated: true, completion: nil)
我写了扩展,因为在某些情况下上面的代码无法工作
extension UIApplication {
class func topViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
let moreNavigationController = tab.moreNavigationController
if let top = moreNavigationController.topViewController, top.view.window != nil {
return topViewController(base: top)
} else if let selected = tab.selectedViewController {
return topViewController(base: selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(base: presented)
}
return base
}
}
用法
let alert = UIAlertController(title: NSLocalizedString(title, comment: ""), message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
UIApplication.topViewController()?.present(alert, animated: true, completion: nil)
键盘显示在专用 window 中。警报、您的视图控制器(请参阅应用程序委托的 window
属性)等也是如此。UIWindow
实例中的 windowLevel
决定了 windows(即 windows 如何相互呈现 above/below)。
我们在我们的应用程序中看到了相同的行为,我们使用自定义 window 作为自定义警报,它始终显示在键盘 window 下方。 window 级别的行为似乎在 iOS 9/10 版本的某个时候发生了变化,因此键盘的 window 始终位于 window 堆栈的顶部。
由于 UIAlertController
的 window 由系统管理,因此第 3 方开发人员可能无法修改此行为。
要检查警报 window 的 window 级别,但是,您可以参考其 view
的 window
的 windowLevel
属性 在你呈现它之后(例如在呈现函数的完成块中)。甚至可能将其更改为一个非常大的值,以试图强制警报的 window 级别。
要跟踪此问题,您可以复制 this radar。
您可以添加 [self.view endEditing:YES];
以确保键盘不会显示。
我断定这应该是 iOS 的一个错误,所以我决定通过创建一个普通的 UIView 来处理它。这是我创建的一个 .xib 文件,用于模拟其中包含 UITextField 的 UIAlertcontoller。希望你的时间至少能节省一些。
https://www.dropbox.com/s/kg2nf9qcm4flhk0/AlertviewWithTextield.xib?dl=0
我有一个 UIAlertController
来自 UIViewController
的呈现,它作为最后一个 UIViewController
被推入 UINavigationController
。这个UIAlertViewController
里面有一个UITextField
。
我的问题是,当我 select 时,UITextField
键盘出现,但 UIAlertViewController
保持居中,部分隐藏在键盘下方。
我的代码如下所示:
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Enter Your PIN" message:@"Please enter your PIN!" preferredStyle:UIAlertControllerStyleAlert];
[alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
[textField setSecureTextEntry:YES];
}];
UIAlertAction* okAction = [UIAlertAction actionWithTitle:@"Confirm"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action) { }];
UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * _Nonnull action) {
}];
[alert addAction:okAction];
[alert addAction:cancelAction];
[self presentViewController:alert animated:YES completion:nil];
截图
应该是自动调整的。 检查您的视图层次结构
You can manage your keyboard based on textField location.
// Call this method somewhere in your view controller in **viewdidload** method
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
//Add in your View Controller which Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your app might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
[self.scrollView scrollRectToVisible:activeField.frame animated:YES];
}
}
// Add in your View Controller which Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
Initialize UITextField * activeField;
Additional methods for tracking the active text field.
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
activeField = nil;
}
你也可以在苹果文档中查看这些概念。 https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html
如果我理解你的话,问题是键盘下方显示了警报。我认为问题在于 UIAlertController 显示在您的 viewController 上?但是键盘是从 rootViewController 显示的。试试这个代码来解决问题
let alert = UIAlertController(title: "Title", message: NSLocalizedString("Message", comment: ""), preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default) { action in }
alert.addAction(okAction)
let rootViewController: UIViewController = UIApplication.shared.windows.last!.rootViewController!
rootViewController.present(alert, animated: true, completion: nil)
我写了扩展,因为在某些情况下上面的代码无法工作
extension UIApplication {
class func topViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
let moreNavigationController = tab.moreNavigationController
if let top = moreNavigationController.topViewController, top.view.window != nil {
return topViewController(base: top)
} else if let selected = tab.selectedViewController {
return topViewController(base: selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(base: presented)
}
return base
}
}
用法
let alert = UIAlertController(title: NSLocalizedString(title, comment: ""), message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
UIApplication.topViewController()?.present(alert, animated: true, completion: nil)
键盘显示在专用 window 中。警报、您的视图控制器(请参阅应用程序委托的 window
属性)等也是如此。UIWindow
实例中的 windowLevel
决定了 windows(即 windows 如何相互呈现 above/below)。
我们在我们的应用程序中看到了相同的行为,我们使用自定义 window 作为自定义警报,它始终显示在键盘 window 下方。 window 级别的行为似乎在 iOS 9/10 版本的某个时候发生了变化,因此键盘的 window 始终位于 window 堆栈的顶部。
由于 UIAlertController
的 window 由系统管理,因此第 3 方开发人员可能无法修改此行为。
要检查警报 window 的 window 级别,但是,您可以参考其 view
的 window
的 windowLevel
属性 在你呈现它之后(例如在呈现函数的完成块中)。甚至可能将其更改为一个非常大的值,以试图强制警报的 window 级别。
要跟踪此问题,您可以复制 this radar。
您可以添加 [self.view endEditing:YES];
以确保键盘不会显示。
我断定这应该是 iOS 的一个错误,所以我决定通过创建一个普通的 UIView 来处理它。这是我创建的一个 .xib 文件,用于模拟其中包含 UITextField 的 UIAlertcontoller。希望你的时间至少能节省一些。
https://www.dropbox.com/s/kg2nf9qcm4flhk0/AlertviewWithTextield.xib?dl=0