Ripristina pre-iOS7 UINavigationController pushViewController animation

Così. Ho appena iniziato a passare il mio codice IOS a IOS7 e ho avuto un po ‘di problemi.

Ho un UINavigationController , che ha ViewControllers figlio e sto usando pushViewController per visualizzare le prossime viste. Per creare un’animazione parallasse con un set di immagini, se personalizzato, UINavigationController per animare un set di UIImageViews e mio figlio ViewControllers hanno tutti un self.backgroundColor = [UIColor clearColor] , trasparenza.

Da quando iOS7, il modo in cui UINavController anima, viene aggiornato, spostando parzialmente il controller della vista corrente e premendo il nuovo viewcontroller, la mia animazione di parallasse sembra schifosa. Vedo che il precedente VC si muove un po ‘e poi scompare. Esiste un modo per ripristinare l’animazione pushViewController di UINavigationController precedente? Non riesco a trovarlo nel codice.

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

Anche provato a usare:

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

Qualcuno ha qualche idea?

Sono riuscito a risolvere il problema con il nuovo tipo di transizione creando una categoria per UINavigationController . Nel mio caso avevo bisogno di ripristinare il vecchio stile di transizione perché ho viewControllers trasparenti che scorrono su uno sfondo statico.

  • 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 

Ho lo stesso problema con i colors di sfondo chiari e le animazioni scadenti, quindi creo la transizione personalizzata per ViewController con la nuova API iOS7. Tutto ciò di cui hai bisogno è semplicemente impostare un delegato per il tuo controller di navigazione:

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

Basta aggiungere questi file nel tuo progetto: MGNavigationTransitioningDelegate .

Ho avuto un problema in cui quando UIViewController A ha fatto pushViewController per spingere UIViewController B, l’animazione push si fermava a circa il 25%, si fermava e quindi faceva scorrere B nel resto del percorso.

Questo NON si è verificato su iOS 6, ma non appena ho iniziato a utilizzare iOS 7 come SDK di base in XCode 5, questo ha avuto inizio.

La correzione è che il controller di visualizzazione B non aveva un backgroundColor impostato sulla sua vista root (la vista root è quella che è il valore di viewController.view, che tipicamente hai impostato in loadView). L’impostazione di un backgroundColor nell’inizializzatore della vista di root ha risolto il problema.

Sono riuscito a risolvere questo come segue:

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

Prima di tutto, non sto usando Storyboard. Ho provato a usare UINavigationController + Retro. Per qualche ragione, UINavigationController sta avendo difficoltà a rilasciare UIViewController in cima allo stack. Ecco la soluzione che funziona per me utilizzando la transizione personalizzata di iOS 7.

  1. Imposta delegato a se stesso.

     navigationController.delegate = self; 
  2. Dichiarare questo UINavigationControllerDelegate.

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

    Si noti che verrà richiamato solo quando l’animazione è impostata su SÌ. Per esempio

     [navigationController pushViewController:currentViewController animated:YES]; 
  3. Crea la class animatore estendendo NSObject. Ho chiamato il mio TransitionAnimator, che è stato modificato da TLTransitionAnimator di TeehanLax all’interno di 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 

    Usa la bandiera di presentazione per impostare la direzione che vuoi animare o quale che sia la condizione che preferisci. Ecco il link al riferimento Apple.

Grazie ragazzi per il feedback. Trovato una soluzione per ricreare completamente il comportamento di UINavigationController. Quando ho quasi finito mi sono imbattuto nella soluzione di Nick Lockwood:

https://github.com/nicklockwood/OSNavigationController

OSNavigationController è una re-implementazione open source di UINavigationController. Attualmente presenta solo un sottoinsieme delle funzionalità di UINavigationController, ma l’objective a lungo termine è quello di replicare il 100% delle funzionalità.

OSNavigationController non è realmente destinato ad essere utilizzato così com’è. L’idea è che puoi forarla e quindi personalizzare facilmente l’aspetto e il comportamento per soddisfare i requisiti speciali che la tua app potrebbe avere. La personalizzazione di OSNavigationController è molto più semplice che provare a personalizzare UINavigationController perché il codice è aperto e non è necessario preoccuparsi dei metodi privati, del comportamento non documentato o delle modifiche di implementazione tra le versioni.

Sovrascrivendo il mio UINavigationController con il suo codice, sono stato in grado di lavorare con le immagini di sfondo in UINavigationcontrollers

Grazie!

Basta aggiungere:

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

Questo:

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

Il risultato finale:

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

Apparentemente in iOS7 c’è un nuovo modo per definire le transizioni personalizzate di UIViewController. Cerca nei documenti per UIViewControllerTransitioningDelegate. Inoltre, ecco un link a un articolo a riguardo: http://www.doubleencore.com/2013/09/ios-7-custom-transitions/

Trovato un’altra grande risorsa per dare una mano:

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

Utilizzando iOS7 TLTransitionAnimator per creare animazioni personalizzate

Ho votato per la risposta di @ Arne, perché la trovo la soluzione più elegante a questo problema. Vorrei solo aggiungere del codice per rispondere al problema di @ Bill dal suo commento sulla soluzione di @ Arne. Ecco la citazione del commento:

Grazie, questo funziona per me. Tuttavia, quando l’utente tocca il pulsante Indietro, ritorna all’animazione abbattuta (perché il pulsante Indietro non chiama popViewControllerRetro). – Bill 3 ottobre alle 12:36

Per chiamare popViewControllerRetro quando viene premuto il pulsante Indietro, c’è un piccolo trucco che puoi eseguire per raggiungere questo objective. Vai nel tuo controller di visualizzazione pushed, importa UIViewController + Retro.h e aggiungi questo codice nel tuo metodo viewWillDisappear:

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

Questa istruzione if rileverà quando viene premuto il pulsante Indietro e chiamerà popViewControllerRetro dalla class della categoria.

I migliori saluti.