2014-10-02 113 views
15

我使用UIAlertController创建了注册表单,并使用方法addTextFieldWithConfigurationHandler添加文本字段。但是有一个小问题。如何同时关闭UIAlertController和键盘?

当表格显示出来时,键盘和模态会以平滑的动画出现。当关闭窗体时,模式首先消失然后键盘消失。这会使键盘突然下降。

如何让模式和键盘优雅地消失?

lazy var alertController: UIAlertController = { [weak self] in 
    let alert = UIAlertController(title: "Alert", message: "This is a demo alert", preferredStyle: .Alert) 
    alert.addTextFieldWithConfigurationHandler { textField in 
     textField.delegate = self 
    } 
    alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil)) 
    return alert 
}() 

@IBAction func alert() { 
    presentViewController(alertController, animated: true, completion: nil) 
} 

func textFieldShouldReturn(textField: UITextField) -> Bool { 
    alertController.dismissViewControllerAnimated(true, completion: nil) 
    return true 
} 

presenting and dismissing

+0

您可以发布您用于创建UIAlertController和操作的代码。谢谢 – 2015-04-12 08:08:47

+0

如果你可以共享一个测试应用程序,我愿意为你检查它。 – Shai 2015-04-12 08:38:10

回答

14

您可以将您的视图控制器或其他物体如您在自己的UIAlertController(alert.transitioningDelegate)的委托,并创建自定义动画解雇。 代码示例:

@interface ViewController() <UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning, UITextFieldDelegate> 
@property (assign, nonatomic) NSTimeInterval keyboardAnimationDuration; 
@property (assign, nonatomic) CGFloat keyboardHeight; 
@property (nonatomic, strong) UIAlertController *alertController; 
@property (nonatomic,strong) id <UIViewControllerTransitioningDelegate> transitioningDelegateForAlertController; 
@end 

@implementation ViewController 

- (void)dealloc { 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    [self subscribeForKeyboardNotification]; 
} 

#pragma mark - Keyboard notifications 

- (void)subscribeForKeyboardNotification { 
    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(keyboardWillAppear:) 
               name:UIKeyboardWillShowNotification 
               object:nil]; 
} 

- (void)keyboardWillAppear:(NSNotification *)notification { 
    self.keyboardAnimationDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; 
    self.keyboardHeight = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height; 
} 

#pragma mark - IBAction 

- (IBAction)showAlertButtonPressed:(id)sender { 
    [self showAlert]; 
} 

- (void)showAlert { 
    self.alertController = [UIAlertController alertControllerWithTitle:@"Alert" 
                      message:@"This is a demo alert" 
                     preferredStyle:UIAlertControllerStyleAlert]; 
    __weak typeof(self) weakSelf = self; 
    [self.alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { 
     textField.delegate = weakSelf; 
    }]; 
    self.transitioningDelegateForAlertController = self.alertController.transitioningDelegate; 
    self.alertController.transitioningDelegate = self; 
    [self.alertController addAction:[UIAlertAction actionWithTitle:@"Ok" 
                 style:UIAlertActionStyleCancel 
                 handler:nil]]; 
    [self presentViewController:self.alertController animated:YES completion:nil]; 
} 

#pragma mark - UITextFieldDelegate 

- (BOOL)textFieldShouldReturn:(UITextField *)textField { 
    [self.alertController dismissViewControllerAnimated:YES completion:nil]; 
    return YES; 
} 

#pragma mark - UIViewControllerTransitioningDelegate 

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented 
                    presentingController:(UIViewController *)presenting 
                     sourceController:(UIViewController *)source { 
    return [self.transitioningDelegateForAlertController animationControllerForPresentedController:presented 
                      presentingController:presenting 
                       sourceController:source]; 
} 

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed { 
    return self; 
} 

#pragma mark - UIViewControllerAnimatedTransitioning 

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext { 
    return self.keyboardAnimationDuration ?: 0.5; 
} 

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext { 
    UIViewController *destination = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; 
    if ([destination isBeingPresented]) 
     [self animatePresentation:transitionContext]; 
    else 
     [self animateDismissal:transitionContext]; 
} 

- (void)animatePresentation:(id <UIViewControllerContextTransitioning>)transitionContext { 
    NSTimeInterval transitionDuration = [self transitionDuration:transitionContext]; 
    UIViewController *fromController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; 
    UIViewController *toController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; 
    UIView *container = transitionContext.containerView; 
    fromController.view.frame = container.bounds; 
    toController.view.frame = container.bounds; 
    toController.view.alpha = 0.0f; 
    [container addSubview:toController.view]; 
    [fromController beginAppearanceTransition:NO animated:YES]; 
    [UIView animateWithDuration:transitionDuration 
        animations:^{ 
         toController.view.alpha = 1.0; 
        } 
        completion:^(BOOL finished) { 
         [fromController endAppearanceTransition]; 
         [transitionContext completeTransition:YES]; 
        }]; 
} 

- (void)animateDismissal:(id <UIViewControllerContextTransitioning>)transitionContext { 
    NSTimeInterval transitionDuration = [self transitionDuration:transitionContext]; 
    UIViewController *fromController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; 
    UIViewController *toController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; 
    [toController beginAppearanceTransition:YES animated:YES]; 
    [UIView animateWithDuration:transitionDuration 
        animations:^{ 
         fromController.view.alpha = 0.0; 
         [fromController.view endEditing:YES]; 
         CGRect frame = fromController.view.frame; 
         frame.origin.y += self.keyboardHeight/2; 
         fromController.view.frame = frame; 
        } 
        completion:^(BOOL finished) { 
         [toController endAppearanceTransition]; 
         [transitionContext completeTransition:YES]; 
        }]; 
} 

@end 

结果:

enter image description here

P.S:我使用的旧警报的过渡委托演示,因为我不能再现原始动画。所以animatePresentation:方法从不使用。

+0

真的很有教育意义,谢谢。你能不能发布你的想法的示例代码? – Thons 2015-04-12 14:11:55

+0

请尝试在我的答案中的代码,并告诉我你期望什么样的动画。 – 2015-04-12 14:15:13

+0

我期待的动画是当警报消失时,键盘会同时消失,就像它们一起出现一样。 – Thons 2015-04-12 14:36:53

2

它很简单。

如果您的UIAlertController代表存在于自我视图控制器。那么您可以在其Dismiss AlertController的委托方法中执行此操作。你可以在你的UIAlertController对象中有[youtTextField resignFirstResponder],它有一个用于解除它的按钮。 (如确定或取消)所以你提交的KeyBoard将被解雇。

我没有尝试过,但它会工作。但是您必须正确处理textField和Alert。

+1

对不起,我不明白这一点。你能提供一小段代码吗? – Randomblue 2015-04-11 04:27:12

+0

@Randomblue在iOS中编写[textfield resignFirstResponder]时,它会从第一响应者辞职并隐藏键盘。因此,在alertdelegate方法中,您可以编写[textfield resignFirstResponder],这样键盘就会隐藏并且提醒也会消失。 – Bhoomi 2015-04-11 10:13:45

0
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 

    { 
     [self.view endEditing:YES]; 
     // or you can write [yourtextfield refignFirstResponder] 
     [alertView dismissWithClickedButtonIndex:buttonIndex animated:TRUE]; 
    } 
+1

您引用的这种委托方法适用于UIAlertView,UIAlertController不使用,因为它的解雇将在UIAction块内处理UIAlertController – 2015-04-11 10:35:39

1

我假设UIAlertController的跳跃是,如果在按下键盘上的'return'之后关闭它。如果是这样,我已经找到了一种方法让警报和键盘顺利退出回收行动。

您需要的类文件

@property (strong, nonatomic) UIAlertController *alertController; 

内声明UIAlertController,你也将需要使用UITextFieldDelegate用的viewController 当添加文本框的UIAlertController这就是你需要设置委托给自己。 (使用weakSelf,因为它是一个块中)

@interface ViewController()<UITextFieldDelegate> 

在你正在拍卖的UIAlertController方法 -

self.alertController = [UIAlertController alertControllerWithTitle:@"Alert" message:@"This is the message" preferredStyle:UIAlertControllerStyleAlert]; 


    __weak typeof(self) weakSelf = self; 

    [self.alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { 
     textField.delegate = weakSelf; 
    }]; 

    [self presentViewController:self.alertController animated:YES completion:nil]; 

添加此UITextField委托方法一旦返回按钮被按下的时会触发键盘。这意味着您可以在UIAlertController在键盘解散之前解除操作,从而使其工作顺利进行。

-(BOOL)textFieldShouldReturn:(UITextField *)textField{ 

    [self.alertController dismissViewControllerAnimated:YES completion:nil]; 

    return YES; 

} 

我测试过了,应该按照您的要求工作。

感谢, 吉姆

+0

谢谢@Jim Tierney。我使用你的代码重新编辑问题,结果显示在屏幕截图的后半部分。 – Thons 2015-04-12 14:17:00

+0

尝试过但不起作用... – SarpErdag 2016-10-17 14:31:25

0
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 

    { 

if (buttonIndex==1) { 

     [[alertView textFieldAtIndex:0] resignFirstResponder]; 

     } else { 

      [[alertView textFieldAtIndex:0] resignFirstResponder]; 

     } 
    } 

使用您的按钮指数(确定或取消按钮指数)

9

我有,你有完全相同的问题,并找到了解决办法偶然。你可能不需要这个了,但对于其他像我这样的缘故,这里的答案:

斯威夫特:

override func canBecomeFirstResponder() -> Bool { 
    return true 
} 

的Objective-C:

- (BOOL)canBecomeFirstResponder { 
    return true; 
} 

只需添加这处理警报的视图控制器中的代码。只在swift中进行测试。

0

没有必要做,你只需要实现这么多的代码的任何东西,它为我工作,无需声明任何形式的委托方法

​​

}

0

调酒viewWillDisappear方法为UIAlertController,并在相应的文本字段或调用endEditing上执行resignFirstResponder:在控制器视图上

我正在使用此ReactiveCocoa:

 let alert = UIAlertController(title: "", message: "", preferredStyle: .Alert) 

     alert.addTextFieldWithConfigurationHandler { 
      textField in 
     } 

     let textField = alert.textFields!.first! 

     alert.rac_signalForSelector(#selector(viewWillDisappear(_:))) 
      .subscribeNext { 
       _ in 
       textField.resignFirstResponder() 
      }