在成为FirstResponder或resignFirstResponder的情况下将对象保持在键盘顶部?

发布于 2024-12-23 22:01:15 字数 720 浏览 1 评论 0原文

我目前在键盘顶部有一个 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];

如果有人以前做过类似的事情,我想知道您用来使动画平滑并使栏看起来“卡在”键盘顶部的设置。

I currently have a UITextField on top of a keyboard. When you tap it, it should stick on top of the keyboard and move up smoothly. I don't know the exact duration and animation type of the keyboard, so it's really bumpy. Here's what I have:

[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];

If anyone has done something like this before, I would like to know the settings you used to make the animation smooth and make it appear that the bar is "stuck" to the top of the keyboard.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一影成城 2024-12-30 22:01:15

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

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

首先,您需要在某处注册通知。您注册的位置取决于负责移动 myTextField 的对象。在我的项目中,该字段的超级视图负责,并且由于我从笔尖加载 UI,因此我在超级视图的 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];
}

UIKit posts UIKeyboardWillShowNotification when it shows the keyboard, and UIKeyboardWillHideNotification when it hides the keyboard. These notifications contain everything you need to properly animate your UITextField.

Let's say your UITextField is in a property called called myTextField.

First, you need to register for the notifications somewhere. Where you register depends on what object is responsible for moving myTextField. In my project, the field's superview is responsible, and since I load my UI from a nib, I do it in the superview's 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];
}

If you use a UIViewController to move the field around, you'll probably want to do it in viewWillAppear:animated:.

You should unregister in your dealloc or viewWillDisappear:animated::

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

Of course the tricky bit is in the keyboardWillHideOrShow: method. First I extract the animation parameters from the notification:

- (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];

The keyboardFrame is in the global coordinate system. I need to convert the frame to the same coordinate system as myTextField.frame, and myTextField.frame is in the coordinate system of myTextField.superview:

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

Next, I compute the frame that I want myTextField to move to. The bottom edge of the new frame should be equal to the top edge of the keyboard's frame:

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

Finally, I animate myTextField to its new frame, using the same animation parameters that the keyboard is using:

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

Here it is all put together:

- (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];
}
故人爱我别走 2024-12-30 22:01:15

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

Set your text field (or a view holding the text field) as the inputAccessoryView of the field that you are editing. It will then automatically be attached to the top of the keyboard and animate appropriately.

堇色安年 2024-12-30 22:01:15

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

in order to make the UITextField to dock to keyboard (with animation), you need to do offset calculations and apply offset changes on the scroll view (assuming UITextField is placed in UIScrollView) using setContentOffset:animation: method.

抱猫软卧 2024-12-30 22:01:15

在键盘通知中使用此代码:

@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)
}

Use this code in your keyboard notification:

@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)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文