当iOS键盘出现时如何上移视图?

5

对于仅有三个文本字段和提交按钮的登录界面,当键盘出现时,我希望视图向上移动,以便在字段未隐藏的情况下,它也不会向上移出视图。

所需的移动量是使提交按钮与键盘保持固定距离。虽然可以将字段移到页面的顶部留出键盘空间,但提交按钮仍然会被隐藏。

我尝试了添加以下内容:

-(void) viewWillAppear:(BOOL)Animated {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
    
}
- (void)viewWillDisappear:(BOOL)animated {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

这个操作将视图向上移动固定的距离,但是会导致字段无法被编辑,即它们被移到了太高的位置。
另一个 SO 答案建议:
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
    [self animateTextField:textField up:YES];
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    [self animateTextField:textField up:NO];
}

-(void)animateTextField:(UITextField*)textField up:(BOOL)up
{
    const int movementDistance = -200; // tweak as needed
    const float movementDuration = 0.3f; // tweak as needed
    
    int movement = (up ? movementDistance : -movementDistance);
    
    [UIView beginAnimations: @"animateTextField" context: nil];
    [UIView setAnimationBeginsFromCurrentState: YES];
    [UIView setAnimationDuration: movementDuration];
    self.view.frame = CGRectOffset(self.view.frame, 0, movement);
    [UIView commitAnimations];
}

我无法弄清如何实施这个。如果你只是按原样不做任何操作,什么也不会发生。我猜你应该以你的文本框的名称重命名textfield,但在这种情况下,你会为每个文本框都这样做吗?我无法使其产生任何效果。

另一个建议是使用类别,例如TPKeyboardAvoiding,但这需要一个滚动视图,在这种情况下我不需要。

2015年难道没有简单明了的解决方案吗?

3个回答

13

以下动画将在用户开始输入时将您的视图(在此情况下为viewForLogin)上移200像素。当文本字段结束编辑时,视图将恢复到原始位置进行动画。不要忘记为文本字段设置代理。

Swift 3

func textFieldDidBeginEditing(_ textField: UITextField) {
    UIView.animate(withDuration: 0.3, animations: {
        self.view.frame = CGRect(x:self.view.frame.origin.x, y:self.view.frame.origin.y - 200, width:self.view.frame.size.width, height:self.view.frame.size.height);

    })
}

func textFieldDidEndEditing(_ textField: UITextField) {
    UIView.animate(withDuration: 0.3, animations: {
        self.viewSupport.frame = CGRect(x:self.viewSupport.frame.origin.x, y:self.viewSupport.frame.origin.y + 200, width:self.viewSupport.frame.size.width, height:self.viewSupport.frame.size.height);

    })
}

Objective-C

-(void)textFieldDidBeginEditing:(UITextField *)textField
{
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:.3];
    [UIView setAnimationBeginsFromCurrentState:TRUE];
    self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y -200., self.view.frame.size.width, self.view.frame.size.height);

    [UIView commitAnimations];


}


-(void)textFieldDidEndEditing:(UITextField *)textField
{
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:.3];
    [UIView setAnimationBeginsFromCurrentState:TRUE];
    self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y +200., self.view.frame.size.width, self.view.frame.size.height);

    [UIView commitAnimations];

}

我想我对视图不是很清楚。我需要将上面的“textField”更改为特定的内容还是通用的?如果我需要更改viewForLogin,那么这是什么?我需要在属性中指定它还是将文本字段放入容器中? - user1904273
我尝试使用self.view,包括更改viewForIpad。但是没有效果。除了如何将视图标识为self.view或其他内容之外,我需要将其放入scrollview中吗?还有什么其他事情我需要做,因为它没有任何效果。 - user1904273
不需要使用scrollview。我已经编辑了答案,只需使用self.view即可完成。检查委托方法是否被调用。 - Fawad Masud
我在上面的方法中放置了一个NSLog语句,但它们没有被调用。如果你有很多文本框,例如-(void)textFieldDidBeginEditing:(UITextField *)firstNameField,接着是-(void)textFieldDidBeginEditing:(UITextField *)lastNameField,我仍然不清楚是否需要为每个单独的文本框都这样做,因为我在这个屏幕上有超过十个字段。无论如何,对于名为textField的字段,该方法都没有被触发。VC确实实现了textfielddelegate协议。 - user1904273
好的。搞定了。我错过了为每个字段设置委托的部分。我猜你确实需要为每个字段都这样做。那么对于文本视图,有没有同样的方法呢? - user1904273
显示剩余3条评论

5

SWIFT 爱好者们,这是你要的。我已经使用了这段代码与 UIView 配合使用,但你应该能够根据需要进行调整以适用于 scrollview。

    func addKeyboardNotifications() {
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(keyboardWillShow(notification:)),
                                               name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(keyboardWillHide(notification:)),
                                               name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

    func keyboardWillShow(notification: NSNotification) {

        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
// if using constraints            
// bottomViewBottomSpaceConstraint.constant = keyboardSize.height
self.view.frame.origin.y -= keyboardSize.height
            UIView.animate(withDuration: duration) {
                self.view.layoutIfNeeded()
            }
        }
    }
    func keyboardWillHide(notification: NSNotification) {

        let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
//if using constraint
//        bottomViewBottomSpaceConstraint.constant = 0
self.view.frame.origin.y = 0
        UIView.animate(withDuration: duration) {
            self.view.layoutIfNeeded()
        }
    }

不要忘记在正确的位置删除通知。

func removeKeyboardNotifications() {
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

2
#define DEVICE_HEIGHT [[UIScreen mainScreen] bounds].size.height       
 -(void)viewDidLoad {

            [super viewDidLoad];

         // register for keyboard notifications

            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(keyboardWillShow:)
                                                         name:UIKeyboardWillShowNotification
                                                       object:self.view.window];

            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(keyboardWillHide:)
                                                         name:UIKeyboardWillHideNotification
                                                       object:self.view.window];

        }

        -(void)viewWillDisappear:(BOOL)animated

        {

        [super viewWillDisappear:animated];
            // unregister for keyboard notifications while not visible.

            [[NSNotificationCenter defaultCenter] removeObserver:self
                                                            name:UIKeyboardWillShowNotification
                                                          object:self.view.window];

            [[NSNotificationCenter defaultCenter] removeObserver:self
                                                            name:UIKeyboardWillHideNotification
                                                          object:self.view.window];
        }

    -(void)keyboardWillShow:(NSNotification *)noti

     {

        NSDictionary* userInfo = [noti userInfo];
        CGRect keyboardRect = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey]   
        CGRectValue];
        keyboardRect = [self.view convertRect:keyboardRect fromView:nil];

        CGRect viewFrame = self.view.frame;
        viewFrame.size.height = DEVICE_HEIGHT - CGRectGetHeight(keyboardRect);

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.1];
        [UIView setAnimationBeginsFromCurrentState:YES];
        self.view.frame = viewFrame;

        CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height  
                               - self.view.bounds.size.height);
        [self.scrollView setContentOffset:bottomOffset animated:NO];

        [UIView commitAnimations];

    }

    -(void)keyboardWillHide:(NSNotification *)noti

     {

        NSDictionary* userInfo = [noti userInfo];
        CGRect keyboardRect = [[userInfo 
                       objectForKey:UIKeyboardFrameEndUserInfoKey]CGRectValue];

        keyboardRect = [self.view convertRect:keyboardRect fromView:nil];

        CGRect viewFrame = self.view.frame;
        viewFrame.size.height = DEVICE_HEIGHT;

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.1];
        [UIView setAnimationBeginsFromCurrentState:YES];
        self.view.frame = viewFrame;
        [UIView commitAnimations];
    }

这里的 DEVICE_HEIGHT 是什么? - Tash Pemhiwa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接