Restaure la animación preINV iOS7 UINavigationController pushViewController

Asi que. Acabo de comenzar la transición de mi código IOS a IOS7, y me encontré con un poco de problema.

Tengo un UINavigationController , que tiene ViewControllers secundarios y estoy usando pushViewController para mostrar las siguientes vistas. Para crear una animación de paralaje con un conjunto de imágenes, si se personaliza el UINavigationController para animar un conjunto de UIImageViews y mi hijo ViewControllers todos tienen un self.backgroundColor = [UIColor clearColor] , transparencia.

Desde iOS7, la forma en que el UINavController anima vc’s infantiles, se actualiza, moviendo parcialmente el controlador de vista actual y en la parte superior empujando el nuevo controlador de vista, mi animación de paralaje se ve horrible. Veo que el VC anterior se mueve un poco y luego desaparece. ¿Hay alguna manera de restaurar la animación anterior de UINavigationController pushViewController? Parece que no puedo encontrar esto en el código.

 WelcomeLoginViewController* welcomeLoginViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"WelcomeLogin"]; [self.navigationController pushViewController:welcomeLoginViewController animated:YES]; 

Incluso intenté usar:

  [UIView animateWithDuration:0.75 animations:^{ [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [self.navigationController pushViewController:welcomeLoginViewController animated:NO]; [UIView setAnimationTransition: forView:self.navigationController.view cache:NO]; }]; 

¿Alguien tiene alguna idea?

UINavigationController solucionar el nuevo tipo de transición creando una categoría para UINavigationController . En mi caso, tuve que volver al antiguo estilo de transición porque tengo viewControllers transparentes que se deslizan sobre un fondo estático.

  • UINavigationController + Retro.h

     @interface UINavigationController (Retro) - (void)pushViewControllerRetro:(UIViewController *)viewController; - (void)popViewControllerRetro; @end 
  • UINavigationController + Retro.m

     #import "UINavigationController+Retro.h" @implementation UINavigationController (Retro) - (void)pushViewControllerRetro:(UIViewController *)viewController { CATransition *transition = [CATransition animation]; transition.duration = 0.25; transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; transition.type = kCATransitionPush; transition.subtype = kCATransitionFromRight; [self.view.layer addAnimation:transition forKey:nil]; [self pushViewController:viewController animated:NO]; } - (void)popViewControllerRetro { CATransition *transition = [CATransition animation]; transition.duration = 0.25; transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; transition.type = kCATransitionPush; transition.subtype = kCATransitionFromLeft; [self.view.layer addAnimation:transition forKey:nil]; [self popViewControllerAnimated:NO]; } @end 

Tengo el mismo problema con los colores de fondo claros y las animaciones cutres, así que creo una transición personalizada para ViewController con la nueva API de iOS7. Todo lo que necesita es simplemente configurar un delegado para su controlador de navegación:

 // NavigationController does not retain delegate, so you should hold it. self.navigationController.delegate = self.navigationTransitioningDelegate; 

Simplemente agregue estos archivos a su proyecto: MGNavigationTransitioningDelegate .

Tuve un problema donde cuando UIViewController A hizo pushController para presionar UIViewController B, la animación de inserción se detendría en aproximadamente 25%, se detendría y luego se deslizaría B en el rest del camino.

Esto NO Ocurrió en iOS 6, pero tan pronto como comencé a usar iOS 7 como el SDK base en XCode 5, esto comenzó a suceder.

La solución es que el controlador de vista B no tenía un backgroundColor configurado en su vista raíz (la vista raíz es la que tiene el valor de viewController.view, que normalmente configura en loadView). Establecer un backgroundColor en el inicializador de la vista raíz solucionó el problema.

Logré solucionar esto de la siguiente manera:

 // CASE 1: The root view for a UIViewController subclass that had a halting animation - (id)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { // Do some initialization ... // self.backgroundColor was NOT being set // and animation in pushViewController was slow and stopped at 25% and paused } return self; } // CASE 2: HERE IS THE FIX - (id)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { // Do some initialization ... // Set self.backgroundColor for the fix! // and animation in pushViewController is no longer slow and and no longer stopped at 25% and paused self.backgroundColor = [UIColor whiteColor]; // or some other non-clear color } return self; } 

Primero, no estoy usando Storyboard. Intenté usar UINavigationController + Retro. Por alguna razón, el UINavigationController está teniendo dificultades para liberar el UIViewController en la parte superior de la stack. Aquí está la solución que funciona para mí usando la transición personalizada de iOS 7.

  1. Establecer delegado en sí mismo.

     navigationController.delegate = self; 
  2. Declare este UINavigationControllerDelegate.

     - (id)navigationController (UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC { TransitionAnimator *animator = [TransitionAnimator new]; animator.presenting = YES; return animator; } 

    Tenga en cuenta que solo se llamará cuando la animación esté configurada en SÍ. Por ejemplo

     [navigationController pushViewController:currentViewController animated:YES]; 
  3. Crea la clase de animador que extiende NSObject. Llamé a mi TransitionAnimator, que fue modificado desde el TLransitionAnimator de TeehanLax dentro de UIViewController-Transitions-Example .

    TransitionAnimator.h

     #import  @interface TransitionAnimator : NSObject  @property (nonatomic, assign, getter = isPresenting) BOOL presenting; @end 

    TransitionAnimator.m

     #import "TransitionAnimator.h" @implementation TransitionAnimator - (NSTimeInterval)transitionDuration:(id )transitionContext { return 0.5f; } - (void)animateTransition:(id )transitionContext{ UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; if (self.presenting) { //ANIMATE VC ENTERING FROM THE RIGHT SIDE OF THE SCREEN [transitionContext.containerView addSubview:fromVC.view]; [transitionContext.containerView addSubview:toVC.view]; toVC.view.frame = CGRectMake(0, 0, 2*APP_W0, APP_H0); //SET ORIGINAL POSITION toVC OFF TO THE RIGHT [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{ fromVC.view.frame = CGRectMake(0, (-1)*APP_W0, APP_W0, APP_H0); //MOVE fromVC OFF TO THE LEFT toVC.view.frame = CGRectMake(0, 0, APP_W0, APP_H0); //ANIMATE toVC IN TO OCCUPY THE SCREEN } completion:^(BOOL finished) { [transitionContext completeTransition:YES]; }]; }else{ //ANIMATE VC EXITING TO THE RIGHT SIDE OF THE SCREEN } } @end 

    Utilice la bandera de presentación para establecer la dirección que desea animar o la condición que prefiera. Aquí está el enlace a la referencia de Apple.

Gracias a todos por los comentarios. Encontré una solución para recrear completamente el comportamiento del UINavigationController. Cuando estaba casi terminado, encontré la solución de Nick Lockwood:

https://github.com/nicklockwood/OSNavigationController

OSNavigationController es una reimplementación de código abierto de UINavigationController. Actualmente presenta solo un subconjunto de la funcionalidad de UINavigationController, pero el objective a largo plazo es replicar el 100% de las funciones.

OSNavigationController no está destinado a ser utilizado tal como está. La idea es que pueda bifurcarlo y luego personalizar fácilmente su aspecto y comportamiento para adaptarse a los requisitos especiales que pueda tener su aplicación. La personalización de OSNavigationController es mucho más simple que tratar de personalizar UINavigationController debido a que el código está abierto y no tiene que preocuparse por métodos privados, comportamiento no documentado o cambios de implementación entre versiones.

Al anular mi UINavigationController con su código, pude trabajar con imágenes de fondo en UINavigationcontrollers

¡Gracias!

Simplemente agregue:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 

Esta:

 [[self window] setBackgroundColor:[UIColor whiteColor]]; 

El resultado final:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions (NSDictionary *)launchOptions { [[self window] setBackgroundColor:[UIColor whiteColor]]; // Override point for customization after application launch. return YES; } 

Aparentemente en iOS7 hay una nueva forma de definir tus propias transiciones UIViewController personalizadas. Consulte en los documentos para UIViewControllerTransitioningDelegate. Además, aquí hay un enlace a un artículo al respecto: http://www.doubleencore.com/2013/09/ios-7-custom-transitions/

Encontré otro gran recurso para ayudar:

http://www.teehanlax.com/blog/custom-uiviewcontroller-transitions

Usando iOS7 TLTransitionAnimator para crear animaciones personalizadas

Voté por la respuesta de @Arne, porque creo que es la solución más elegante para este problema. Me gustaría agregar un código para responder al problema de @Bill a partir de su comentario sobre la solución de @Arne. Aquí hay un comentario:

Gracias, esto funciona para mí. Sin embargo, cuando el usuario toca el botón Atrás, vuelve a la animación reventada (porque el botón Atrás no llama a popViewControllerRetro). – Bill 3 de octubre a las 12:36

Para llamar a popViewControllerRetro cuando se presiona el botón Atrás, hay un pequeño truco que puede realizar para lograr esto. Vaya a su controlador de vista presionada, importe UIViewController + Retro.h y agregue este código en su método viewWillDisappear:

 - (void)viewWillDisappear:(BOOL)animated { if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound) { [self.navigationController popViewControllerRetro]; } [super viewWillDisappear:animated]; } 

Esta instrucción if detectará cuando se presione el botón Atrás y llamará a popViewControllerRetro desde la clase de categoría.

Atentamente.