如果模态ViewController演示文稿样式为UIModalPresentationFormSheet,则iPad键盘不会被忽略

时间:2010-07-30 14:17:56

标签: ios iphone objective-c uitextfield first-responder

注意:

从iOS 4.3开始,请参阅已接受的答案(不是最受欢迎的答案)。

问题是关于在iPad键盘中发现的行为,如果在带有导航控制器的模态对话框中显示,则拒绝解除该行为。

基本上,如果我使用以下行显示导航控制器:

navigationController.modalPresentationStyle = UIModalPresentationFormSheet;

键盘拒绝被解雇。如果我注释掉这一行,键盘就会消失。

...

我有两个textFields,用户名和密码; username有一个Next按钮,密码有一个Done按钮。如果我在模态导航控制器中显示它,键盘将不会消失。

WORKS

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
[self.view addSubview:b.view];

不工作

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
UINavigationController *navigationController = 
[[UINavigationController alloc]
 initWithRootViewController:b];
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
navigationController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:navigationController animated:YES];
[navigationController release];
[b release];

如果我删除导航控制器部件并将'b'作为模态视图控制器单独显示,则可以正常工作。导航控制器是问题吗?

WORKS

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
b.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:b animated:YES];
[b release];

WORKS

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
UINavigationController *navigationController = 
    [[UINavigationController alloc]
         initWithRootViewController:b];
[self presentModalViewController:navigationController animated:YES];
[navigationController release];
[b release];

13 个答案:

答案 0 :(得分:172)

Apple工程师将其归类为“按预期工作”。我暂时为此提交了一个错误。他们的理由是用户经常会以模态形式输入数据,因此他们试图“有用”并保持键盘可见,而模态视图中的各种过渡通常会导致键盘重复显示/隐藏。 / p> 在开发人员论坛上编辑Apple工程师的here is the response

  

你的观点是否有机会呈现UIModalPresentationFormSheet风格?为了避免频繁的进出动画,即使没有第一响应者,键盘有时也会保持在屏幕上。这不是一个错误。

这给很多人带来了问题(包括我自己),但目前似乎没有办法解决这个问题。

<强>更新

在iOS 4.3及更高版本中,您现在可以在视图控制器上实现`-disablesAutomaticKeyboardDismissal'以返回NO:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

这解决了这个问题。

答案 1 :(得分:149)

如果您使用UINavigationController显示模态,请务必小心。然后,您必须在导航控制器上设置disablesAutomaticKeyboardDismissal,而不是在视图控制器上。您可以使用类别轻松完成此操作。

文件:UINavigationController + KeyboardDismiss.h

#import <Foundation/Foundation.h>

@interface UINavigationController (KeyboardDismiss)

- (BOOL)disablesAutomaticKeyboardDismissal;

@end

文件:UINavigationController + KeyboardDismiss.m

#import "UINavigationController+KeyboardDismiss.h"

@implementation UINavigationController(KeyboardDismiss)

- (BOOL)disablesAutomaticKeyboardDismissal
{
    return NO;
}

@end

不要忘记在您使用的文件中导入类别 UINavigationController的。

答案 2 :(得分:115)

在以模态方式呈现的视图控制器中,只需覆盖disablesAutomaticKeyboardDismissal即可返回NO

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

答案 3 :(得分:51)

我通过使用UIModalPresentationPageSheet演示文稿样式解决了这个问题,并在我呈现它之后立即调整它。像这样:

viewController.modalPresentationStyle = UIModalPresentationPageSheet;
viewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:viewController animated:YES];
viewController.view.superview.autoresizingMask = 
    UIViewAutoresizingFlexibleTopMargin | 
    UIViewAutoresizingFlexibleBottomMargin;    
viewController.view.superview.frame = CGRectMake(
    viewController.view.superview.frame.origin.x,
    viewController.view.superview.frame.origin.y,
    540.0f,
    529.0f
);
viewController.view.superview.center = self.view.center;
[viewController release];

答案 4 :(得分:1)

如果您切换不同的模态显示,则可以让键盘消失。它并不漂亮,也没有动画,但你可以让它消失。

如果有一个解决方案会很棒,但现在这个很有用。你可以将它楔入UIViewController的类别中,并在你想要键盘消失时调用它:

@interface _TempUIVC : UIViewController
@end

@implementation _TempUIVC
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}
@end

@implementation UIViewController (Helpers)

- (void)_dismissModalViewController {
    [self dismissModalViewControllerAnimated:NO];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
    [self release];
}

- (void)forceKeyboardDismissUsingModalToggle:(BOOL)animated {
    [self retain];
    _TempUIVC *tuivc = [[_TempUIVC alloc] init];
    tuivc.modalPresentationStyle = UIModalPresentationCurrentContext;
    [self presentModalViewController:tuivc animated:animated];
    if (animated) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_dismissModalViewController) name:UIKeyboardDidHideNotification object:nil];
    } else
        [self _dismissModalViewController];
    [tuivc release];
}

@end

当你查看DeanDppear / viewDidDisappear并调用所有这些方法时,请注意这一点。就像我说的那样,它不漂亮,但确实有效。

- 亚当

答案 5 :(得分:1)

你也可以通过简单地检查成语来在通用应用程序中解决这个问题,如果它是iPad,不要自动弹出键盘,让用户点击他们想要编辑的任何内容。

可能不是最好的解决方案,但它非常简单,不需要任何花哨的黑客攻击下一个主要的iOS版本:)

答案 6 :(得分:1)

对于那些遇到UINavigationController问题的人,请在此处查看我对类似问题的回答: https://stackoverflow.com/a/10507689/321785

编辑: 我认为这是对Miha Hribar解决方案的改进(因为决定应该发生在哪里),而不是Pascal关于UIViewController上类别的评论

答案 7 :(得分:1)

将此代码放在viewWillDisappear中:当前控制器的方法是解决此问题的另一种方法:

Class UIKeyboardImpl = NSClassFromString(@"UIKeyboardImpl");
id activeInstance = [UIKeyboardImpl performSelector:@selector(activeInstance)];
[activeInstance performSelector:@selector(dismissKeyboard)];

答案 8 :(得分:0)

可能不返回NO,但是YES。所以它可以消失。

你还有textFieldShouldEndEditing返回YES吗?

为什么你在解雇[nextResponder becomeFirstResponder]?!抱歉我现在看到了

  

我也有很多UITextViews   都有“可编辑”   属性设置为FALSE。

我们可以假设它们中没有一个tag值为secondField.tag+1吗?如果是这样,你告诉他们成为第一响应者,而不是让第一响应者辞职。如果结构可能会放入一些NSLog()。

答案 9 :(得分:0)

我确定你看过这个,但是你确定你的控制器类已经正确连接为UITextField委托了,对吗?

答案 10 :(得分:0)

可能不是一个完美的解决方案,但可以工作 [self.view endEditing:YES];
从实现按钮或手势的任何地方到呈现模态

答案 11 :(得分:0)

我发现disablesAutomaticKeyboardDismissal并添加disablesAutomaticKeyboardDismissal功能在模态对话框中对我的UITextField无效。

屏幕键盘不会消失。

我的解决方法是在我的对话框中禁用所有文本输入控件,然后在几分之一秒后重新启用相关控件。

似乎iOS看到没有UITextField控件被启用,那么它 摆脱了键盘。

答案 12 :(得分:0)

Swift 4.1:
extension UINavigationController {
   override open var disablesAutomaticKeyboardDismissal: Bool {
      return false
   }
}