Autolayout Constraint - Клавиатура
Я застрял, пытаясь плавно анимировать табличное представление, которое имеет ограничение на автоматическое размещение. У меня есть ссылка на ограничение "keyboardHeight" в моем.h, и я связал это в IB. Все, что я хочу сделать, это анимировать табличное представление с помощью клавиатуры, когда оно появляется. Вот мой код:
- (void)keyboardWillShow:(NSNotification *)notification
{
NSDictionary *info = [notification userInfo];
NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardFrame = [kbFrame CGRectValue];
CGFloat height = keyboardFrame.size.height;
[UIView animateWithDuration:animationDuration animations:^{
self.keyboardHeight.constant = -height;
[self.view setNeedsLayout];
}];
}
Дело в том, что блок анимации мгновенный, и я вижу, что пробел появляется до того, как клавиатура закончила анимацию. Так что, в основном, я вижу белый фон вида, когда клавиатура анимируется. Я не могу сделать анимацию длиться до тех пор, пока анимация клавиатуры.
Я подхожу к этому неправильно? Заранее спасибо!
4 ответа
Попробуйте это так:
self.keyboardHeight.constant = -height;
[self.view setNeedsUpdateConstraints];
[UIView animateWithDuration:animationDuration animations:^{
[self.view layoutIfNeeded];
}];
Запомните этот шаблон, потому что это должен быть правильный способ обновления макетов на основе ограничений (согласно WWDC). Вы также можете добавить или удалить NSLayoutConstraint
пока ты звонишь setNeedsUpdateConstraints
после.
Если вы используете UITableViewController, iOS должен автоматически приспосабливать размер клавиатуры для настройки contentInsets. Но если ваш tableView находится внутри UIViewController, вы, вероятно, хотели бы использовать это:
KeyboardLayoutConstraint в рамках Spring. Самое простое решение, которое я нашел до сих пор.
Попробуйте следующий код. В этом случае табличное представление располагается у нижнего края экрана.
- (void)keyboardWillShow:(NSNotification *)notification { // UIKeyboardWillShowNotification
NSDictionary *info = [notification userInfo];
NSValue *keyboardFrameValue = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardFrame = [keyboardFrameValue CGRectValue];
BOOL isPortrait = UIDeviceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation);
CGFloat keyboardHeight = isPortrait ? keyboardFrame.size.height : keyboardFrame.size.width;
// constrBottom is a constraint defining distance between bottom edge of tableView and bottom edge of its superview
constrBottom.constant = keyboardHeight;
// or constrBottom.constant = -keyboardHeight - in case if you create constrBottom in code (NSLayoutConstraint constraintWithItem:...:toItem:...) and set views in inverted order
[UIView animateWithDuration:animationDuration animations:^{
[tableView layoutIfNeeded];
}];
}
- (void)keyboardWillHide:(NSNotification *)notification { // UIKeyboardWillHideNotification
NSDictionary *info = [notification userInfo];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
constrBottom.constant = 0;
[UIView animateWithDuration:animationDuration animations:^{
[tableView layoutIfNeeded];
}];
}
Подход, который я выбрал, состоит в том, чтобы добавить представление, соответствующее размеру клавиатуры. Добавьте это под вашим табличным представлением, или вводом текста, или чем-то еще, и это будет толкать вещи, когда появится клавиатура.
Вот как я настроил иерархию представления:
NSDictionary *views = @{@"chats": self.chatsListView, @"reply": self.replyBarView, @"fakeKeyboard":self.fakeKeyboardView};
[self.view addVisualConstraints:@"V:|-30-[chats][reply][fakeKeyboard]|" views:views];
И тогда биты клавиш вида, следующего за размером клавиатуры, выглядят так:
- (void)keyboardWillShow:(NSNotification *)notification
{
// Save the height of keyboard and animation duration
NSDictionary *userInfo = [notification userInfo];
CGRect keyboardRect = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
self.desiredHeight = CGRectGetHeight(keyboardRect);
self.duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
[self animateSizeChange];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
self.desiredHeight = 0.0f;
[self animateSizeChange];
}
- (CGSize)intrinsicContentSize
{
return CGSizeMake(UIViewNoIntrinsicMetric, self.desiredHeight);
}
- (void)animateSizeChange
{
[self invalidateIntrinsicContentSize];
// Animate transition
[UIView animateWithDuration:self.duration animations:^{
[self.superview layoutIfNeeded];
}];
}
Хорошая вещь, позволяющая этому конкретному представлению обрабатывать его изменение размера, состоит в том, что вы можете позволить контроллеру представления игнорировать его, и вы также можете повторно использовать это представление в любом месте вашего приложения, где вы хотите сдвинуть все вверх.
Полный файл находится здесь: https://gist.github.com/shepting/6025439