如何同时关闭 UIAlertController 和键盘?
Posted
技术标签:
【中文标题】如何同时关闭 UIAlertController 和键盘?【英文标题】:How to dismiss an UIAlertController and the keyboard simultaneously? 【发布时间】:2014-10-02 13:20:37 【问题描述】:我创建了一个带有UIAlertController
的注册表单,并使用addTextFieldWithConfigurationHandler
方法添加了一个文本字段。但是有一个小问题。
当表单出现时,键盘和模式会以流畅的动画出现。关闭表单时,模态框首先消失,然后然后键盘消失。这使得键盘突然向下坠落。
如何让模式和键盘优雅地消失?
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
【问题讨论】:
您能否发布您用于创建 UIAlertController 和操作的代码。谢谢 如果您可以分享一个测试应用程序,我愿意为您检查。 【参考方案1】:您可以将您的视图控制器或其他对象设置为您的 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
结果:
P.S.:我使用旧警报的过渡委托进行演示,因为我无法重现原始动画。所以animatePresentation:
方法永远不会被使用。
【讨论】:
真的很有启发性,谢谢。能否请您发布您的想法的示例代码? 请试试我回答中的代码,告诉我你期待什么样的动画。 我很期待警报消失时键盘同时消失的动画,就像它们一起出现一样。【参考方案2】:我遇到了与您完全相同的问题,并偶然找到了解决方案。你可能不再需要这个了,但是为了像我这样的其他人,这里是答案:
斯威夫特:
override func canBecomeFirstResponder() -> Bool
return true
目标-C:
- (BOOL)canBecomeFirstResponder
return true;
只需在处理警报的视图控制器中添加此代码。仅在 swift 中测试。
【讨论】:
【参考方案3】:其实很简单。
如果您的 UIAlertController
委托存在于 self 视图控制器中。那么你可以在 Dismiss AlertController 的委托方法中执行此操作。你可以在你的 UIAlertController 对象中 [youtTextField resignFirstResponder]
,它有一个关闭它的按钮。 (如 OK 或 Cancel) 这样您提供的键盘将被关闭。
我没有尝试过,但它会起作用。但你必须正确处理 textField 和 Alert。
【讨论】:
对不起,我不明白这一点。你能提供一小段代码吗? @Randomblue 在 ios 中,当您编写 [textfield resignFirstResponder] 时,它会从第一响应者中退出并隐藏键盘。所以在 alertdelegate 方法中你可以写 [textfield resignFirstResponder] 所以键盘会隐藏并且警报也会关闭..【参考方案4】:我假设 UIAlertController 的跳下是在您按下键盘上的“返回”后它消失。如果是这样,我已经找到一种方法让警报和键盘从返回操作中顺利解除。
您需要在类文件中声明 UIAlertController
@property (strong, nonatomic) UIAlertController *alertController;
您还需要将 UITextFieldDelegate 与 viewController 一起使用 将 textField 添加到 UIAlertController 时,您需要将其委托设置为 self。 (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;
我已经对此进行了测试,应该可以完全按照您的要求工作。
谢谢, 吉姆
【讨论】:
谢谢你,@Jim Tierney。我用你的代码重新编辑了问题,结果显示在截图的后半部分。【参考方案5】: - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
[self.view endEditing:YES];
// or you can write [yourtextfield refignFirstResponder]
[alertView dismissWithClickedButtonIndex:buttonIndex animated:TRUE];
【讨论】:
你提到的这个委托方法是针对 UIAlertview 的,UIAlertController 不使用它,因为它的解除将在 UIAlertController 使用的 UIAction 块中处理【参考方案6】:- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
if (buttonIndex==1)
[[alertView textFieldAtIndex:0] resignFirstResponder];
else
[[alertView textFieldAtIndex:0] resignFirstResponder];
使用您的按钮索引(确定或取消按钮索引)
【讨论】:
【参考方案7】:不需要做任何事情,你只需要实现这么多代码,它对我有用,不需要声明任何类型的委托方法
- (void)showAlert
self.alertController = [UIAlertController alertControllerWithTitle:@"Alert"
message:@"Enter Name:"
preferredStyle:UIAlertControllerStyleAlert];
[self.alertController addTextFieldWithConfigurationHandler:^(UITextField *textField)
];
[self.alertController addAction:[UIAlertAction actionWithTitle:@"Ok"
style:UIAlertActionStyleCancel
handler:nil]];
[self presentViewController:self.alertController animated:YES completion:nil];
【讨论】:
【参考方案8】:调动 UIAlertController 的 viewWillDisappear 方法,并在对应的文本字段上执行 resignFirstResponder 或在控制器的视图上调用 endEditing:
我正在使用这个 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()
【讨论】:
以上是关于如何同时关闭 UIAlertController 和键盘?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 SWIFT 中不执行任何操作就关闭 UIAlertController?
我们如何在没有用户输入的情况下创建和关闭 UIAlertController? (迅速)
在 Swift 中点击返回键时如何关闭 UIAlertController?
关闭 UIViewController 而不关闭其顶部的警报