在eventFirstResponder或resignFirstResponder的情况下,将对象保持在键盘顶部?

时间:2012-01-02 18:31:48

标签: iphone objective-c uitextfield resignfirstresponder becomefirstresponder

我目前在键盘上有一个UITextField。点击它时,它应该粘在键盘顶部并平稳向上移动。我不知道键盘的确切持续时间和动画类型,所以它真的很颠簸。这就是我所拥有的:

[theTextView resignFirstResponder];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.25];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
// Frame changes go here (move down 216px)
[UIView commitAnimations];

[theTextView becomeFirstResponder];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.25];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
// Frame changes go here (move up 216px)
[UIView commitAnimations];

如果有人之前做过这样的事情,我想知道你用来使动画变得平滑的设置,并让它看起来像是“卡在”键盘的顶部。

4 个答案:

答案 0 :(得分:45)

UIKit在显示键盘时发布UIKeyboardWillShowNotification,在隐藏键盘时发布UIKeyboardWillHideNotification。这些通知包含正确设置UITextField动画所需的一切。

假设您的UITextField位于名为myTextField的属性中。

首先,您需要在某处注册通知。您注册的位置取决于移动myTextField的对象。在我的项目中,该字段的superview负责,因为我从一个笔尖加载我的UI,我在superview的awakeFromNib中执行:

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

如果您使用UIViewController移动字段,则可能希望在viewWillAppear:animated:中执行此操作。

您应该在deallocviewWillDisappear:animated:

中取消注册
- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

当然,棘手的一点是keyboardWillHideOrShow:方法。首先,我从通知中提取动画参数:

- (void)keyboardWillHideOrShow:(NSNotification *)note
{
    NSDictionary *userInfo = note.userInfo;
    NSTimeInterval duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationCurve curve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];

    CGRect keyboardFrame = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

keyboardFrame位于全局坐标系中。我需要将帧转换为与myTextField.frame相同的坐标系,而myTextField.frame位于myTextField.superview的坐标系中:

    CGRect keyboardFrameForTextField = [self.myTextField.superview convertRect:keyboardFrame fromView:nil];

接下来,我计算我希望myTextField移动到的帧。新帧的下边缘应该等于键盘框架的上边缘:

    CGRect newTextFieldFrame = self.myTextField.frame;
    newTextFieldFrame.origin.y = keyboardFrameForTextField.origin.y - newTextFieldFrame.size.height;

最后,我使用键盘正在使用的相同动画参数将myTextField设置为新帧:

    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
        self.myTextField.frame = newTextFieldFrame;
    } completion:nil];
}

这里全部放在一起:

- (void)keyboardWillHideOrShow:(NSNotification *)note
{
    NSDictionary *userInfo = note.userInfo;
    NSTimeInterval duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationCurve curve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];

    CGRect keyboardFrame = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGRect keyboardFrameForTextField = [self.myTextField.superview convertRect:keyboardFrame fromView:nil];

    CGRect newTextFieldFrame = self.myTextField.frame;
    newTextFieldFrame.origin.y = keyboardFrameForTextField.origin.y - newTextFieldFrame.size.height;

    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
        self.myTextField.frame = newTextFieldFrame;
    } completion:nil];
}

答案 1 :(得分:5)

将文本字段(或包含文本字段的视图)设置为您正在编辑的字段的inputAccessoryView。然后它会自动连接到键盘顶部并进行适当的动画制作。

答案 2 :(得分:0)

为了使UITextField停靠到键盘(带动画),您需要使用setContentOffset:animation:方法进行偏移计算并在滚动视图上应用偏移更改(假设UITextField放在UIScrollView中)。

答案 3 :(得分:0)

在键盘通知中使用以下代码:

@objc func keyboardWillShowNotification(notification: Notification) {
    let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.size.height ?? 216
    let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double ?? 0.25
    let curve = (notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? UInt ?? 7) << 16
    tableViewBottomConstraint.constant = keyboardHeight - submitButtonContainer.frame.size.height

    UIView.animate(withDuration: duration, delay: 0, options: [UIViewAnimationOptions(rawValue: curve)], animations: {
        // Animation
    }, completion: nil)
}