我创建了一个包含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
}
答案 0 :(得分:15)
您可以将视图控制器或其他对象设置为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:
方法。
答案 1 :(得分:9)
我遇到了完全相同的问题并偶然找到了解决方案。你可能不再需要这个,但为了像我这样的其他人,这就是答案:
夫特:
override func canBecomeFirstResponder() -> Bool {
return true
}
目标-C:
- (BOOL)canBecomeFirstResponder {
return true;
}
只需在处理警报的视图控制器中添加此代码即可。仅在swift中测试过。
答案 2 :(得分:2)
非常简单。
如果您的UIAlertController
代表出现在自我 View Controller中。那么你可以在它的Dismiss AlertController的委托方法中做到这一点。您可以在UIAlertController对象中[youtTextField resignFirstResponder]
,它有一个用于关闭它的按钮。 (例如“确定”或“取消”)因此您所呈现的KeyBoard将被解雇。
我没有尝试过,但它会起作用。但你必须正确处理textField和Alert。
答案 3 :(得分:1)
我认为UIAlertController的跳跃是在你按下键盘上的'return'后它解散了。如果是这样,我找到了一种让Alert和键盘顺利解除返回动作的方法。
您需要在类文件
中声明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;
}
我已经对此进行了测试,并且应该按照您的要求运行。
谢谢, 吉姆
答案 4 :(得分:0)
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
[self.view endEditing:YES];
// or you can write [yourtextfield refignFirstResponder]
[alertView dismissWithClickedButtonIndex:buttonIndex animated:TRUE];
}
答案 5 :(得分:0)
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex==1) {
[[alertView textFieldAtIndex:0] resignFirstResponder];
} else {
[[alertView textFieldAtIndex:0] resignFirstResponder];
}
}
使用您的按钮索引(确定或取消按钮索引)
答案 6 :(得分:0)
不需要做任何事情你只需要实现这么多代码,它对我有用,不需要声明任何类型的委托方法
- (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];
}
答案 7 :(得分:0)
用于UIAlertController的Swizzle viewWillDisappear方法,并在correspodent文本字段上执行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()
}