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.
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];
}
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.
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:
.
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)
}
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