Держать объект поверх клавиатуры в случае становления FirstResponder или resignFirstResponder?

В настоящее время у меня есть 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 ответа

Решение

UIKit сообщений UIKeyboardWillShowNotification когда он показывает клавиатуру, и UIKeyboardWillHideNotification когда он скрывает клавиатуру. Эти уведомления содержат все необходимое для правильной анимации вашего UITextField,

Скажем ваш UITextField находится в собственности под названием называется myTextField,

Во-первых, вам нужно где-то зарегистрироваться для получения уведомлений. Место регистрации зависит от того, какой объект отвечает за перемещение myTextField, В моем проекте ответственным является супервизор поля, и так как я загружаю свой интерфейс из пера, я делаю это в суперпредставлении 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:,

Вы должны отменить регистрацию в своем dealloc или же viewWillDisappear: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];
}

Установите текстовое поле (или представление, содержащее текстовое поле) как inputAccessoryView поля, которое вы редактируете. Затем он будет автоматически прикреплен к верхней части клавиатуры и соответствующим образом анимирован.

Для того, чтобы UITextField пристыковался к клавиатуре (с анимацией), необходимо выполнить вычисления смещения и применить изменения смещения к представлению прокрутки (при условии, что UITextField помещен в UIScrollView) с помощью setContentOffset:animation: метод.

Используйте этот код в уведомлении клавиатуры:

@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)
}
Другие вопросы по тегам