Utrzymywanie obiektu na klawiaturze w przypadku becomeFirstResponder lub resignFirstResponder?

Obecnie mam UITextField na klawiaturze. Po dotknięciu powinien on trzymać się na klawiaturze i płynnie poruszać się w górę. Nie znam dokładnego czasu trwania i rodzaju animacji klawiatury, więc jest naprawdę wyboista. Oto co mam:

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

Jeśli ktoś robił coś takiego wcześniej, chciałbym znać ustawienia, których użyłeś, aby animacja była płynna i sprawiała wrażenie, że pasek jest "przyklejony" do górnej części klawiatury.

Author: iosfreak, 2012-01-02

4 answers

UIKit posty {[7] } kiedy pokazuje klawiaturę i UIKeyboardWillHideNotification kiedy ukrywa klawiaturę. Powiadomienia te zawierają wszystko, czego potrzebujesz do poprawnego animowania UITextField.

Powiedzmy, że Twój UITextField znajduje się w nieruchomości zwanej myTextField.

Najpierw musisz gdzieś się zarejestrować, aby otrzymywać powiadomienia. Miejsce rejestracji zależy od tego, jaki obiekt jest odpowiedzialny za przenoszenie myTextField. W moim projekcie superview pola jest odpowiedzialny, a ponieważ Ładuję swój UI z stalówki, robię to w 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];
}

Jeśli używasz UIViewController do przesuwania pola, prawdopodobnie będziesz chciał to zrobić w viewWillAppear:animated:.

Powinieneś wyrejestrować się w swoim dealloc lub viewWillDisappear:animated::

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

Oczywiście tricky bit jest w metodzie keyboardWillHideOrShow:. Najpierw wyodrębniam parametry animacji z powiadomienia:

- (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 znajduje się w globalnym układzie współrzędnych. Muszę przekonwertować ramkę na ten sam układ współrzędnych co myTextField.frame, a myTextField.frame jest we współrzędnych układ myTextField.superview:

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

Następnie obliczam klatkę, do której chcę się przenieść. Dolna krawędź nowej ramki powinna być równa górnej krawędzi ramki klawiatury:

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

Na koniec animuję myTextField do nowej klatki, używając tych samych parametrów animacji, których używa Klawiatura:

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

Tutaj wszystko jest poukładane:

- (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];
}
 45
Author: rob mayoff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-02 23:45:27

Ustaw swoje pole tekstowe (lub widok trzymający pole tekstowe) jako inputAccessoryView edytowanego pola. Zostanie on Automatycznie dołączony do górnej części klawiatury i odpowiednio animowany.

 5
Author: jrturton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-02 19:11:48

Aby UITextField zadokował do klawiatury (z animacją), należy wykonać obliczenia przesunięcia i zastosować zmiany przesunięcia w widoku przewijania (zakładając, że UITextField jest umieszczony w UIScrollView) przy użyciu metody setContentOffset:animation:.

 0
Author: Tatvamasi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-02 18:42:21

Użyj tego kodu w powiadomieniu na klawiaturze:

@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)
}
 0
Author: huync,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-19 05:29:11