Как имитировать анимацию клавиатуры на iOS 7, чтобы добавить кнопку "Готово" к цифровой клавиатуре?
Я делал что-то вроде этого, чтобы имитировать анимацию клавиатуры в старой версии iOS.
CGRect keyboardBeginFrame;
[[note.userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] getValue:&keyboardBeginFrame];
self.doneKeyboardButton.frame = CGRectMake(0, (keyboardBeginFrame.origin.y + keyboardBeginFrame.size.height) - 53, 106, 53);
[[[[UIApplication sharedApplication] windows] lastObject] addSubview:self.doneKeyboardButton];
CGPoint newCenter = CGPointMake(self.doneKeyboardButton.superview.frame.origin.x + self.doneKeyboardButton.frame.size.width/2,
self.doneKeyboardButton.superview.frame.size.height - self.doneKeyboardButton.frame.size.height/2);
[UIView animateWithDuration:[[note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]-.02
delay:.0
options:[[note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]
animations:^{
self.contentView.frame = CGRectOffset(self.contentView.frame, 0, -TextFieldViewMovement);
self.doneKeyboardButton.center = newCenter;
}
completion:nil];
Однако это перестало работать на iOS7. Кажется, что возвращаемые значения уже не совсем правильны, а кнопка "Готово" больше не имитирует анимацию отображения клавиатуры.
Ответы
Ответ 1
В iOS 7 клавиатура использует новую, недокументированную анимационную кривую. Хотя некоторые отметили, что использование недокументированного значения для опции анимации работает, я предпочитаю использовать следующее:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
[UIView setAnimationCurve:[notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue]];
[UIView setAnimationBeginsFromCurrentState:YES];
// work
[UIView commitAnimations];
В то время как анимация на основе блоков является рекомендацией, кривая анимации, возвращаемая с уведомлением о клавиатуре, является UIViewAnimationCurve
, тогда как параметр, который вам нужно передать на анимацию на основе блоков, - это UIViewAnimationOptions
. Использование традиционных методов анимации UIView позволяет напрямую передавать значение. Самое главное, что это будет использовать новую кривую бездокументальной анимации (целочисленное значение 7) и заставить анимацию соответствовать клавиатуре. И он будет работать так же хорошо на iOS 6 и 7.
Ответ 2
У меня была такая же проблема, и мне удалось заставить анимацию работать со следующими параметрами для iOS 7:
[UIView animateWithDuration:0.5
delay:0
usingSpringWithDamping:500.0f
initialSpringVelocity:0.0f
options:UIViewAnimationOptionCurveLinear
animations:animBlock
completion:completionBlock];
EDIT: эти значения были получены с помощью отладки, а может изменяться с новыми версиями iOS. @DavidBeck answer работает для меня в iOS 7, поэтому я связываю его здесь.
Ответ 3
Apple использует некоторую недокументированную анимацию со значением 7 в iOS 7.
Однако объявление UIViewAnimationCurve
определяет значения от 0 до 3
typedef enum {
UIViewAnimationCurveEaseInOut, // 0
UIViewAnimationCurveEaseIn,
UIViewAnimationCurveEaseOut,
UIViewAnimationCurveLinear // 3
} UIViewAnimationCurve;
UIViewAnimationOptions
, который вам нужен для анимации на основе блоков, определяется как
enum {
// ...
UIViewAnimationOptionCurveEaseInOut = 0 << 16,
UIViewAnimationOptionCurveEaseIn = 1 << 16,
UIViewAnimationOptionCurveEaseOut = 2 << 16,
UIViewAnimationOptionCurveLinear = 3 << 16,
UIViewAnimationOptionTransitionNone = 0 << 20,
// ...
};
Кажется, что Apple резервирует 4 бита для кривой анимата (20 - 16 = 4), которая позволяет использовать значения от 0 до 15 (поэтому, вероятно, есть больше недокументированных значений).
С помощью этих знаний вы можете просто преобразовать UIViewAnimationCurve
в UIViewAnimationOptions
, сдвинув его примерно на 16 бит. В вашем примере это означает:
options:[[note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue] << 16
Ответ 4
Вы можете использовать блок animateWithDuration
и задать внутри него кривую. Он чист и работает хорошо.
UIViewAnimationCurve curve = [[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
double duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
[UIView animateWithDuration:duration
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
[UIView setAnimationCurve:curve];
/* ANIMATION HERE */
// don't forget layoutIfNeeded if you use autolayout
}
completion:nil];
Счастливое кодирование!
UPDATE
Вы можете использовать простую категорию UIViewController, написанную мной https://github.com/Just-/UIViewController-KeyboardAnimation
Ответ 5
Если вы хотите добавить кнопку на панели инструментов (подобно тому, как это делает мобильный Safari), вы можете просто использовать свойство inputAccessoryView
(оба UITextField
и UITextView
его есть) и сэкономить все проблемы, Этот скрытый камень мало известен, я рад, что наткнулся на него.
Он работает как на iOS 6, так и на iOS 7, я использую его в своем приложении Routie.
Ответ 6
Это работает отлично для меня... Продолжительность поймана, когда отображается клавиатура. Я знаю, что жесткое кодирование параметров означает, что это может сломаться в будущем, но оно работает на 7 и 8. Это для нас сейчас достаточно хорошо...
[UIView animateWithDuration:self.animationDuration
delay:0.0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[self.view layoutIfNeeded]; completion:^(BOOL finished) {
if (finished)
{
if (completion)
completion();
}
}];