Restaurer l’animation pushViewController UINavigationController avant iOS7

Alors. Je viens juste de commencer la transition de mon code IOS vers IOS7 et j’ai rencontré un problème.

J’ai un UINavigationController , qui a des enfants ViewControllers et j’utilise pushViewController pour afficher les vues suivantes. Pour créer une animation de parallaxe avec un ensemble d’images, si elle est personnalisée, UINavigationController pour animer un ensemble de UIImageViews et mes enfants ViewControllers ont tous une self.backgroundColor = [UIColor clearColor] .

Depuis iOS7, la façon dont UINavController anime les vc enfants, est mise à jour, en déplaçant partiellement le contrôleur de vue actuel et en poussant le nouveau viewcontroller, mon animation de parallaxe semble anormale. Je vois que le VC précédent bouge un peu puis disparaît. Y a-t-il un moyen de restaurer l’animation pushViewController d’ UINavigationController précédente? Je n’arrive pas à trouver cela dans le code.

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

Même essayé en utilisant:

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

Quelqu’un at-il des indices?

J’ai réussi à contourner le nouveau type de transition en créant une catégorie pour UINavigationController . Dans mon cas, je devais revenir à l’ancien style de transition car j’ai des viewControllers transparents qui glissent sur un arrière-plan statique.

  • 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 

J’ai le même problème avec des couleurs d’arrière-plan claires et des animations minables. Je crée donc une transition personnalisée pour ViewController avec la nouvelle API iOS7. Il vous suffit de définir un délégué pour votre contrôleur de navigation:

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

Ajoutez simplement ces fichiers dans votre projet: MGNavigationTransitioningDelegate .

J’avais un problème lorsque UIViewController A faisait un pushViewController pour pousser UIViewController B, l’animation push s’arrêtait à environ 25%, s’arrêtait, puis glissait B dans le rest.

Cela ne s’est PAS produit sur iOS 6, mais dès que j’ai commencé à utiliser iOS 7 en tant que SDK de base dans XCode 5, cela a commencé.

Le correctif est que le contrôleur de vues B n’avait pas de jeu backgroundColor dans sa vue racine (la vue racine est celle qui correspond à la valeur de viewController.view, que vous définissez généralement dans loadView). La définition d’un backgroundColor dans l’initialiseur de cette vue racine a résolu le problème.

J’ai réussi à résoudre ce problème comme suit:

 // 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; } 

Tout d’abord, je n’utilise pas Storyboard. J’ai essayé d’utiliser UINavigationController + Retro. Pour une raison quelconque, UINavigationController a du mal à libérer le UIViewController en haut de la stack. Voici la solution qui fonctionne pour moi en utilisant la transition personnalisée iOS 7.

  1. Définir le délégué sur soi-même.

     navigationController.delegate = self; 
  2. Déclarez ce UINavigationControllerDelegate.

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

    Notez qu’il ne sera appelé que lorsque l’animation est définie sur YES. Par exemple

     [navigationController pushViewController:currentViewController animated:YES]; 
  3. Créez la classe d’animation qui étend NSObject. J’ai appelé le mien TransitionAnimator, qui a été modifié à partir de TLTransitionAnimator de TeehanLax dans 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 

    Utilisez l’indicateur de présentation pour définir la direction que vous souhaitez animer ou la condition que vous préférez. Voici le lien vers la référence Apple.

Merci les gars pour les commentaires. Nous avons trouvé une solution pour recréer complètement le comportement de UINavigationController. Quand j’ai presque fini, j’ai rencontré la solution de Nick Lockwood:

https://github.com/nicklockwood/OSNavigationController

OSNavigationController est une ré-implémentation open source de UINavigationController. Il ne comporte actuellement qu’un sous-ensemble des fonctionnalités de UINavigationController, mais l’objective à long terme est de répliquer 100% des fonctionnalités.

OSNavigationController n’est pas vraiment destiné à être utilisé tel quel. L’idée est que vous pouvez le fourrer et ensuite personnaliser facilement son apparence et son comportement pour répondre à toutes les exigences particulières de votre application. Personnaliser OSNavigationController est beaucoup plus simple que d’essayer de personnaliser UINavigationController, car le code est ouvert et que vous n’avez pas à vous soucier des méthodes privées, du comportement non documenté ou des changements d’implémentation entre les versions.

En remplaçant mon UINavigationController par son code, j’ai pu travailler avec des images de fond dans UINavigationcontroller

Merci!

Ajoutez simplement:

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

Ce:

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

Le résultat final:

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

Apparemment, dans iOS7, vous pouvez définir vos propres transitions UIViewController. Regardez dans les documents pour UIViewControllerTransitioningDelegate. En outre, voici un lien vers un article à ce sujet: http://www.doubleencore.com/2013/09/ios-7-custom-transitions/

J’ai trouvé une autre ressource formidable pour vous aider:

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

Utilisation d’iOS7 TLTransitionAnimator pour créer des animations personnalisées

J’ai voté pour la réponse de @Arne, car je trouve que c’est la solution la plus élégante à ce problème. Je voudrais juste append du code pour répondre au problème de @ Bill à partir de son commentaire sur la solution de @ Arne. Voici un commentaire:

Merci, cela fonctionne pour moi. Cependant, lorsque l’utilisateur appuie sur le bouton Précédent, il revient à l’animation interrompue (car le bouton Précédent n’appelle pas popViewControllerRetro). – Bill Oct 3 à 12:36

Pour appeler popViewControllerRetro quand le bouton retour est pressé, vous pouvez effectuer un petit hack pour y parvenir. Accédez à votre contrôleur de vue poussée, importez UIViewController + Retro.h et ajoutez ce code dans votre méthode viewWillDisappear:

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

Cette instruction if détectera quand le bouton Back est pressé et appellera popViewControllerRetro à partir de la classe de catégorie.

Meilleures salutations.