Синхронизация анимаций в клавиатуреПоказать клавиатуруWillHide - аппаратная клавиатура и виртуальная клавиатура одновременно
Преамбула
Итак, у меня есть приложение с секцией чата, и я синхронизую анимацию скрывающейся клавиатуры и показываю ее с ростом и падением входа в чат.
Вот код, который я использую:
ШОУ:
- (void) keyboardWillShow:(NSNotification *)note {
NSDictionary *keyboardAnimationDetail = [note userInfo];
UIViewAnimationCurve animationCurve = [keyboardAnimationDetail[UIKeyboardAnimationCurveUserInfoKey] integerValue];
CGFloat duration = [keyboardAnimationDetail[UIKeyboardAnimationDurationUserInfoKey] floatValue];
NSValue* keyboardFrameBegin = [keyboardAnimationDetail valueForKey:UIKeyboardFrameBeginUserInfoKey];
CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];
// working for hardware keyboard
//UIViewAnimationOptions options = (UIViewAnimationOptions)animationCurve;
// working for virtual keyboard
UIViewAnimationOptions options = (animationCurve << 16);
[UIView animateWithDuration:duration delay:0.0 options:options animations:^{
textView.frame = CGRectMake(0, self.view.bounds.size.height - keyboardFrameBeginRect.size.height, self.view.bounds.size.width, -40);
} completion:nil];
}
HIDE:
- (void) keyboardWillHide:(NSNotification *)note {
NSDictionary *keyboardAnimationDetail = [note userInfo];
UIViewAnimationCurve animationCurve = [keyboardAnimationDetail[UIKeyboardAnimationCurveUserInfoKey] integerValue];
CGFloat duration = [keyboardAnimationDetail[UIKeyboardAnimationDurationUserInfoKey] floatValue];
// hardware keyboard
//UIViewAnimationOptions options = (UIViewAnimationOptions)animationCurve;
// virtual keyboard
UIViewAnimationOptions options = (animationCurve << 16);
[UIView animateWithDuration:duration delay:0.0 options:options animations:^{
textView.frame = CGRectMake(0, self.view.bounds.size.height, self.view.bounds.size.width, -40);
} completion:nil];
}
Это отлично работает с виртуальной клавиатурой, но если клавиатураWillShow: или keyboardWillHide: вызывается в результате отсоединения или подключения аппаратной клавиатуры, анимация отстает. Я могу исправить это, изменив UIViewAnimationOptions
Заменить:
// Works with virtual keyboard
UIViewAnimationOptions options = (animationCurve << 16);
С
// working for firstResponder keyboard
UIViewAnimationOptions options = (UIViewAnimationOptions)animationCurve;
Но при этом теперь анимация virtualKeyboard отстает
Я понимаю, что анимация аппаратной клавиатуры не очень распространена, и это, возможно, не самая важная проблема, но мне нравится все, чтобы просто работать!
Примеры
VirtualKeyboard w/(animationCurve < 16) - РАБОТА
![VirtualKeyboard w/ (animationCurve << 16)]()
VirtualKeyboard w/(UIViewAnimationOptions) animationCurve - BROKEN
![VirtualKeyboard w/ (UIViewAnimationOptions)animationCurve]()
HardwareKeyboard w/(animationCurve < 16) - BROKEN
![HardwareKeyboard w/ (animationCurve << 16)]()
HardwareKeyboard w/(UIViewAnimationOptions) animationCurve - WORKING
![HardwareKeyboard w/ (UIViewAnimationOptions)animationCurve]()
Примечания
Чтобы имитировать аппаратную клавиатуру в симуляторе cmd + shft + k
Да, это реплицируется на реальном устройстве.
В случае, если вы этого хотите, здесь остальная часть моего кода, только для целей репликации
ДОБАВИТЬ ТЕКСТ ПРОСМОТР
textView = [UITextView new];
textView.layer.borderWidth = 10;
textView.layer.borderColor = [UIColor blackColor].CGColor;
textView.frame = CGRectMake(0, self.view.bounds.size.height, self.view.bounds.size.width, -40);
[self.view addSubview:textView];
UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc]init];
[tap addTarget:self action:@selector(handleTap:)];
[self.view addGestureRecognizer:tap];
// OBSERVE KEYBOARD
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
РУЧКА:
- (void) handleTap:(UITapGestureRecognizer *)tap {
NSLog(@"tapped");
[textView resignFirstResponder];
}
Вопрос:
Что здесь происходит, и есть ли хороший способ получить согласованную анимацию, независимо от виртуальной/аппаратной клавиатуры?
Я понимаю, что это долго, спасибо за чтение!
Ответы
Ответ 1
Поскольку кривая анимации, которую Apple посылает вам в уведомлении на клавиатуре, не имеет соответствующего бита UIViewAnimationOption, вам нужно перейти к неблокированной анимации старой школы и использовать кривую напрямую:
NSTimeInterval duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [note.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
[UIView beginAnimations:@"SomeAnimationID" context:NULL];
[UIView setAnimationCurve:curve];
[UIView setAnimationDuration:duration];
// Animation code
[UIView commitAnimations];
Ответ 2
keyboardWillShow:
NSDictionary *info = [notification userInfo];
CGRect keyboardFrame = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue];
NSTimeInterval duration = [info[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [info[UIKeyboardAnimationCurveUserInfoKey] integerValue];
[self layoutIfNeeded];
[UIView animateWithDuration:duration delay:0 options:(curve << 20) animations:^{
[self.keyboardConstraint setConstant:keyboardFrame.size.height];
[self layoutIfNeeded];
} completion:nil];