Анимируйте клавиатуру синхронно с UIView, одновременно смахивая края назад в iOS7
Я хотел бы получить поведение, подобное приложению "Сообщения" (также распространенное в большинстве приложений для работы с текстовыми сообщениями) в iOS7, где в представлении беседы, проведенном вправо от левого края экрана, будет действовать как кнопка "Назад" в UINavigationController.
Мне удалось реализовать это поведение, однако, если клавиатура открыта в представлении представления, когда я начинаю проводить пальцем назад, клавиатура застревает и не анимируется с видом вправо, когда я двигаю пальцем. Я хотел бы анимировать клавиатуру и представление представления как одно целое, а не так, как будто клавиатура находится поверх других представлений, и они анимируются позади нее, что я и получаю сейчас (см. Второй снимок экрана):
(ОБНОВЛЕНИЕ: обратите внимание, что клавиатура со временем исчезнет после завершения анимации основного вида; на что я обращаю внимание - это положение клавиатуры во время процесса пролистывания и когда вы продолжаете касаться устройства на половине пути, который не находится в синхронизировать с фактическим видом. Второй снимок экрана поясняет это желаемое поведение. Мне также интересно, почему это не по умолчанию.)
Эту проблему легко воспроизвести, просто создав новое приложение iPhone с мастер-деталями в Xcode 5.0.2 и добавив текстовое поле в подробное представление (предпочтительно где-то в верхней половине) в StoryBoard, запустив приложение, добавив элемент, нажав на него, чтобы перейти к подробному виду и нажав на текстовое поле, которое вы добавили. Проведите по краю с левой стороны устройства, удерживая на нем палец, и вы увидите проблему.
Желаемое поведение:
Текущее поведение:
3 ответа
К сожалению, нет встроенного метода для этого. Я очень надеюсь, что будет что-то вроде UIScrollViewKeyboardDismissModeInteractive
за UIViewController
s.
На данный момент, чтобы сделать любую анимацию между viewControllers, вы должны использовать transitionCoordinator:
- (BOOL)animateAlongsideTransition:(void (^)(id <UIViewControllerTransitionCoordinatorContext>context))animation
completion:(void (^)(id <UIViewControllerTransitionCoordinatorContext>context))completion;
- (BOOL)animateAlongsideTransitionInView:(UIView *)view
animation:(void (^)(id <UIViewControllerTransitionCoordinatorContext>context))animation
completion:(void (^)(id <UIViewControllerTransitionCoordinatorContext>context))completion;
Для клавиатуры вы должны сделать что-то вроде этого:
[self.transitionCoordinator animateAlongsideTransitionInView:self.keyboardSuperview
animation:
^(id<UIViewControllerTransitionCoordinatorContext> context) {
self.keyboardSuperview.x = self.view.width;
}
completion:nil];
Что касается keyboardSuperview
- вы можете получить это, создав подделку inputAccessoryView
:
self.textField.inputAccessoryView = [[UIView alloc] init];
Тогда супервьюз будет self.textField.inputAccessoryView.superview
Это должно просто работать автоматически, но иногда это не из-за некоторых условий.
Если текущий firstResponder
находится внутри активного UIViewController
и уволить UINavigationController
Механизм, ожидаемая анимация клавиатуры (горизонтальная) будет выполняться автоматически. Поэтому иногда это поведение по умолчанию нарушается другими странными факторами, и клавиатура начинает исчезать с анимацией скольжения вместо горизонтальной анимации.
Я провел несколько дней с отладкой внутреннего UIKit материала (вокруг методов needDeferredTransition
, allowCustomTransition
и другое) найти один особый фактор, который играет ключевую роль в моем случае.
Я обнаружил, что логика внутри UIPeripheralHost
проверки frame
тока UIViewConroller
вид, frame
из UINavigationController
вид (контейнер) и экран size
и, если все это не равно друг другу, UIPeripheralHost
решает, что текущая ситуация выглядит как модальное окно, и устанавливает флаг allowCustomTransition = NO
, Это отключение UINavigationController
горизонтальная анимация
Исправление проблемы с frame
S полностью решает мою проблему.
Если у вас возникли те же проблемы, вы можете попытаться отладить внутренний UIKit-контент вокруг этих частных методов и найти условия, которые отключают горизонтальную анимацию:
Вы можете использовать https://github.com/cotap/TAPKeyboardPop если вам не нужно ничего особенного.
В моем случае у меня есть некоторая логика, связанная с UIKeyboardWillShowNotification
а также UIKeyboardWillHideNotification
которые были уволены по жесту "смахивание к спине". Я объединяю этот ответ и TAPKeyboardPop
и вот что у меня есть:
- (void)beginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animated {
[super beginAppearanceTransition:isAppearing animated:animated];
if (isAppearing || !animated || !_keyboardIsShown) {
return;
}
if ([self respondsToSelector:@selector(transitionCoordinator)]) {
UIView *keyboardView = self.searchBar.inputAccessoryView.superview;
[self.searchBar becomeFirstResponder];
[self.transitionCoordinator animateAlongsideTransitionInView:keyboardView
animation:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
CGRect endFrame = CGRectOffset(keyboardView.frame, CGRectGetWidth(keyboardView.frame), 0);
keyboardView.frame = endFrame;
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
if (![context isCancelled]) {
[self.searchBar resignFirstResponder];
}
}];
}
}
РЕДАКТИРОВАТЬ:
Я добавил> поддержку iOS7 и логику, чтобы знать, когда клавиатура отображается (_keyboardIsShown
установлен в UIKeyboardWillShowNotification/UIKeyboardWillHideNotification
или в UIKeyboardDidHideNotification/UIKeyboardDidShowNotification
).