2014-10-02 87 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() 
      }