2012-01-25 15 views
24

Attualmente sto usando [self presentModalViewController :newVC animated:YES]. Desidero presentare nuovoViewcontroller da sinistra/destra/alto/basso con un effetto push. Ho provato ad usare CATransition ma visualizza uno schermo nero tra la transizione.Animate presentModalViewController da destra/sinistra

+0

Per le altre persone con questo problema, ho postato la soluzione che ho trovato qui: http://stackoverflow.com/questions/6876292/iphone-presentmodalviewcontroller-with-transition-from-right/10842991 # 10842991 –

risposta

1

ci sono solo quattro: UIModalTransitionStyles

UIModalTransitionStyleCoverVertical 
UIModalTransitionStyleFlipHorizontal 
UIModalTransitionStyleCrossDissolve 
UIModalTransitionStylePartialCurl 

Per esempio:

UIViewController *controller = [[[MyViewController alloc] init] autorelease]; 
UIModalTransitionStyle trans = UIModalTransitionStyleFlipHorizontal; 
[UIView beginAnimations: nil context: nil]; 
[UIView setAnimationTransition: trans forView: [self window] cache: YES]; 
[navController presentModalViewController: controller animated: NO]; 
[UIView commitAnimations]; 
3

Ho avuto lo stesso problema. Dire che si desidera presentare un controller di vista 2 dal punto di vista di controllo 1. Nel primo controller della vista usare

[self presentModalViewController: controller animated: NO]]; 

Nel secondo controller della vista, in viewWillAppear: metodo di aggiungere il codice

CATransition *animation = [CATransition animation]; 

    [animation setDelegate:self]; 
    [animation setType:kCATransitionPush]; 
    [animation setSubtype:kCATransitionFromRight]; 

    [animation setDuration:0.40]; 
    [animation setTimingFunction: 
    [CAMediaTimingFunction functionWithName: 
     kCAMediaTimingFunctionEaseInEaseOut]]; 


    [self.view.layer addAnimation:animation forKey:kCATransition]; 

Funzionerà bene. Se lo schermo nero viene di nuovo, se si sta utilizzando controller di navigazione, sostituire

[self.view.layer addAnimation:animation forKey:kCATransition]; 

con

[self.navigationController.view.layer addAnimation:animation forKey:kCATransition]; 
+0

provato questo. Ancora il problema schermo nero persiste – user1085093

+0

Ho anche il problema schermo nero. Prima che il controller modale venga premuto, appare una schermata nera. Qualcuno ha risolto il problema? – bolonn

90

Quando presenti:

CATransition *transition = [CATransition animation]; 
transition.duration = 0.3; 
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
transition.type = kCATransitionPush; 
transition.subtype = kCATransitionFromRight; 
[self.view.window.layer addAnimation:transition forKey:nil]; 

[self presentModalViewController:viewCtrl animated:NO]; 

Quando respingere:

CATransition *transition = [CATransition animation]; 
transition.duration = 0.3; 
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
transition.type = kCATransitionPush; 
transition.subtype = kCATransitionFromLeft; 
[self.view.window.layer addAnimation:transition forKey:nil]; 
[self dismissModalViewControllerAnimated:NO]; 
+0

Perfetto. Questa è la risposta giusta – rmvz3

+5

Sembra che non funzioni più su iOS 8, poiché il VC di presentazione si sta spostando invece di quello presentato. hai qualche idea su come aggiustarlo? – Maiaux

+1

¿Come posso rimuovere gli effetti di dissolvenza? – jalopezsuarez

-1

È può impostare un transitioningDelegate sul controller della vista che si desidera presentare. È necessario conformarsi ai protocolli UIViewControllerTransitioningDelegate e UIViewControllerAnimatedTransitioning. E implementando animateTransition(transitionContext: UIViewControllerContextTransitioning) è possibile animare le viewview dei controller di visualizzazione.

funzione che esegue la transizione

class fromViewController : UIViewController { 
    let transitionManager = TransitionManager() 

    func transitionToViewController() { 
     toController.transitioningDelegate = transitionManager 
     presentViewController(toController, animated: true, completion: nil) 
    } 
} 

Poi il TransitionManager assomiglia:

import UIKit 

class TransitionManager : UIPercentDrivenInteractiveTransition { 
    var presenting = false 
} 

// MARK: UIViewControllerAnimatedTransitioning 
extension TransitionManager : UIViewControllerAnimatedTransitioning { 
    func animateTransition(transitionContext: UIViewControllerContextTransitioning) { 
     let container = transitionContext.containerView() 
     let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)! 
     let toView = transitionContext.viewForKey(UITransitionContextToViewKey)! 

     let offScreenRight = CGAffineTransformMakeTranslation(container.frame.width, 0) 
     let offScreenLeft = CGAffineTransformMakeTranslation(-container.frame.width, 0) 

     toView.transform = self.presenting ? offScreenRight : offScreenLeft 

     container.addSubview(toView) 
     container.addSubview(fromView) 
     let duration = self.transitionDuration(transitionContext) 

     UIView.animateWithDuration(duration, delay: 0.0, usingSpringWithDamping: 1, initialSpringVelocity: 0.8, options: nil, animations: { 
      fromView.transform = self.presenting ? offScreenLeft : offScreenRight 
      toView.transform = CGAffineTransformIdentity 

      }, completion: { finished in 
      transitionContext.completeTransition(true) 
     }) 
    } 


    func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval { 
     return 0.3 
    } 
} 


// MARK: UIViewControllerTransitioningDelegate 
extension TransitionManager : UIViewControllerTransitioningDelegate { 
    func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? { 
     self.presenting = true 
     return self 
    } 

    func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { 
     self.presenting = false 
     return self 
    } 
} 
+0

Non funziona. Il caso 'self.presenting == false' restituisce uno schermo nero con la cornice sbagliata – Barry

+0

@Barry Questo funziona per me non usando le passe piuttosto che le transizioni manuali tra i controller in diversi storyboard. Dai un'occhiata al codice che hai postato sopra sei cercando di sovrascrivere una transizione push di un UINavigationController. Hai avuto il seguito nello storyboard impostato per spingere piuttosto che presentare? –

1

Dopo X> = 4 ore di lavoro, questo funziona senza "strappi" o altri artefatti di fondo:

class AboutTransition: NSObject, UIViewControllerAnimatedTransitioning { 

    let presenting: Bool 
    let duration: NSTimeInterval 

    init(presenting: Bool, duration: NSTimeInterval = 0.25) { 
     self.presenting = presenting 
     self.duration = duration 
    } 

    @objc func transitionDuration(ctx: UIViewControllerContextTransitioning) -> NSTimeInterval { 
     return duration 
    } 

    @objc func animateTransition(ctx: UIViewControllerContextTransitioning) { 
     let duration = transitionDuration(ctx) 
     let containerView = ctx.containerView() 
     let fromViewController = ctx.viewControllerForKey(UITransitionContextFromViewControllerKey)! 
     let toViewController = ctx.viewControllerForKey(UITransitionContextToViewControllerKey)! 
     let fromView = fromViewController.view // 7.0 & 8.0 compatible vs. viewForKey: 
     let toView = toViewController.view  // 7.0 & 8.0 compatible vs. viewForKey: 

     containerView.addSubview(fromView) 
     containerView.addSubview(toView) 

     let offScreenRight = CGAffineTransformMakeTranslation(containerView.frame.width, 0) 
     let offScreenLeft = CGAffineTransformMakeTranslation(-containerView.frame.width, 0) 

     fromView.transform = CGAffineTransformIdentity 
     toView.transform = self.presenting ? offScreenRight : offScreenLeft 

     UIView.animateWithDuration(duration, delay:0, options:UIViewAnimationOptions(0), animations: { 
      fromView.transform = self.presenting ? offScreenLeft : offScreenRight 
      toView.transform = CGAffineTransformIdentity 

     }, completion: { (finished: Bool) in 
      ctx.completeTransition(finished) 
      if finished { 
       fromView.removeFromSuperview() 
       fromView.frame = toView.frame // reset the frame for reuse, otherwise frame transforms will accumulate 
      } 
     }) 
    } 
} 

Quindi in AppDelegate.swift:

@UIApplicationMain 
class AppDelegate: UIResponder, UIApplicationDelegate, UINavigationControllerDelegate { 

    lazy var window: UIWindow? = { 
     return UIWindow(frame: UIScreen.mainScreen().bounds) 
    }() 

    lazy var storyboard = UIStoryboard(name: "Main", bundle: nil) 

    lazy var nav: UINavigationController = { 
     var r = self.storyboard.instantiateInitialViewController() as! UINavigationController 
     r.delegate = self 
     return r 
    }() 

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 
     self.window!.rootViewController = nav 
     self.window!.makeKeyAndVisible() 

     // .. other setup 

     return true 
    } 

    // ... 


    // MARK: - UINavigationControllerDelegate 

    func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { 
     // Example of a SettingsViewController which pushes AboutViewController 
     if fromVC is SettingsViewController && toVC is AboutViewController { // Push to About 
      return AboutTransition(presenting: true) 
     } else if fromVC is AboutViewController && toVC is SettingsViewController { // Pop to Settings 
      return AboutTransition(presenting: false) 
     } 
     return nil 
    } 
} 

questo presuppone un app utilizza lo storyboard di default con un VC iniziale come UINavigationController