ios iphone ios7 keyboard gesture

Animar el teclado en sincronía con UIView mientras se desliza de nuevo en iOS7



iphone keyboard (3)

Me gustaría obtener el comportamiento similar a la aplicación Messages (también es común en la mayoría de las aplicaciones de mensajes de texto) en iOS7, donde en una vista de conversación, deslizar el dedo desde el borde izquierdo de la pantalla se comporta como el botón de retroceso en un controlador UINavigation.

He logrado implementar este comportamiento, sin embargo, si el teclado está abierto en la vista de presentación, cuando comienzo a deslizar hacia atrás, el teclado se atasca y no se anima con la vista a la derecha cuando muevo el dedo. Me gustaría animar el teclado y la vista de presentación como una unidad, no como si el teclado estuviera encima de las otras vistas y estuvieran animándose detrás, lo que obtengo ahora (vea la segunda captura de pantalla):

( ACTUALIZACIÓN: tenga en cuenta que el teclado eventualmente desaparecerá una vez finalizada la animación de la vista principal; en lo que estoy enfocado es en la posición del teclado durante el proceso de deslizamiento, y cuando sigue tocando el dispositivo por la mitad del camino, no está sincronice con la vista real. La segunda captura de pantalla aclara el comportamiento deseado. También me pregunto por qué no es el predeterminado.

Es fácil replicar el problema simplemente creando una nueva aplicación de iPhone con detalles maestros en Xcode 5.0.2 y agregando un Campo de texto a la vista de detalles (preferiblemente en algún lugar en la mitad superior) en el Tablero de Historias, ejecutando la aplicación, agregando un elemento , tocándolo para ir a la vista de detalles y hacer clic en el campo de texto que agregó. Deslice el borde desde el lado izquierdo del dispositivo mientras mantiene el dedo sobre él y verá el problema.

Comportamiento deseado:

Comportamiento actual:


Simplemente debería funcionar automáticamente, pero a veces no es así debido a algunas condiciones.

Si el firstResponder actual se encuentra dentro de UIViewController activo y se despide a través del mecanismo UINavigationController , la animación del teclado (horizontal) esperada se realizará automáticamente. Por lo tanto, a veces este comportamiento predeterminado se rompe por otros factores extraños y el teclado comienza a desaparecer con una animación deslizante en lugar de una animación horizontal.

Pasé algunos días con tareas de depuración de UIKit interno (alrededor de los métodos needDeferredTransition allowCustomTransition needDeferredTransition , allowCustomTransition y otros) para encontrar un factor especial que juega un papel clave en mi caso.

Descubrí que la lógica dentro de UIPeripheralHost verifica el frame de la UIViewConroller actual de UIViewConroller , el frame de la vista de UINavigationController (contenedor) y el size pantalla y, si no es igual entre sí, UIPeripheralHost decide que esta situación actual parece una ventana modal y establece la bandera allowCustomTransition = NO . Esa desactivación de UINavigationController animación horizontal específica.

Solucionar el problema con el frame s soluciona completamente mi problema.

Si experimenta los mismos problemas, puede intentar depurar los elementos UIKit internos con estos métodos privados y encontrar las condiciones que desactivan la animación horizontal:

https://github.com/JaviSoto/iOS8-Runtime-Headers/blob/master/Frameworks/UIKit.framework/UIPeripheralHost.h

https://github.com/JaviSoto/iOS8-Runtime-Headers/blob/master/Frameworks/UIKit.framework/_UIViewControllerKeyboardAnimationStyle.h


Puede usar https://github.com/cotap/TAPKeyboardPop si no necesita nada especial.

En mi caso, tengo algo de lógica conectada con UIKeyboardWillShowNotification y UIKeyboardWillHideNotification que se UIKeyboardWillShowNotification UIKeyboardWillHideNotification de "deslizar hacia atrás". Combino esta respuesta con TAPKeyboardPop y esto es lo que tengo:

- (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]; } }]; } }

EDITAR:

He agregado la compatibilidad y la lógica de iOS7 para saber cuándo se muestra el teclado ( _keyboardIsShown se establece en UIKeyboardWillShowNotification/UIKeyboardWillHideNotification o en UIKeyboardDidHideNotification/UIKeyboardDidShowNotification ).


Desafortunadamente, no hay un método incorporado para hacer eso. Realmente espero que haya algo como UIScrollViewKeyboardDismissModeInteractive para UIViewController s.

Por ahora, para hacer animaciones intermedias entre viewControllers, debes usar unitor de 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;

Para el teclado debes hacer algo como esto:

[self.transitionCoordinator animateAlongsideTransitionInView:self.keyboardSuperview animation: ^(id<UIViewControllerTransitionCoordinatorContext> context) { self.keyboardSuperview.x = self.view.width; } completion:nil];

En cuanto a keyboardSuperview , puede obtenerlo creando un inputAccessoryView falso:

self.textField.inputAccessoryView = [[UIView alloc] init];

Entonces la supervisión será self.textField.inputAccessoryView.superview