2012-01-25 16 views
24

Obecnie używam [self presentModalViewController :newVC animated:YES]. Chcę przedstawić newViewcontroller od lewej/prawej/górnej/dolnej z efektem wypychania. Próbowałem użyć CATransition, ale wyświetla czarny ekran pomiędzy przejściami.Animować presentModalViewController od prawej/lewej

+0

Dla innych osób z tego problemu, napisałem rozwiązanie znalazłem tutaj: http://stackoverflow.com/questions/6876292/iphone-presentmodalviewcontroller-with-transition-from-right/10842991 # 10842991 –

Odpowiedz

1

Istnieją tylko cztery UIModalTransitionStyles:

UIModalTransitionStyleCoverVertical 
UIModalTransitionStyleFlipHorizontal 
UIModalTransitionStyleCrossDissolve 
UIModalTransitionStylePartialCurl 

Na przykład:

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

miałem ten sam problem. Załóżmy, że chcesz przedstawić kontroler View 2 z widokiem na kontrolerze 1. W pierwszym kontrolerze widoku używać

[self presentModalViewController: controller animated: NO]]; 

W drugim kontrolerze widoku, w viewWillAppear: metoda dodać kod

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

Będzie pracować w porządku. Jeśli czarny ekran przychodzi ponownie, jeśli używasz kontrolera nawigacyjnego zastąpić

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

z

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

próbował tego. Nadal pozostaje problem z czarnym ekranem. – user1085093

+0

Mam również problem z czarnym ekranem. Przed wciśnięciem kontrolera modalnego pojawi się czarny ekran. Ktoś rozwiązał problem? – bolonn

90

Gdy obecny:

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

Po zwolnieniu:

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

Idealny. To jest właściwa odpowiedź. – rmvz3

+5

Wygląda na to, że nie działa już na iOS 8, ponieważ prezentowany VC porusza się zamiast prezentowanego. Każdy pomysł, jak to naprawić? – Maiaux

+1

¿Jak mogę usunąć efekty zanikania? – jalopezsuarez

-1

Ty można ustawić transitioningDelegate na kontrolerze widoku, który chcesz zaprezentować. Musisz przestrzegać protokołów UIViewControllerTransitioningDelegate i UIViewControllerAnimatedTransitioning. I implementując animateTransition(transitionContext: UIViewControllerContextTransitioning) można animować widoki podglądu kontrolerów.

Funkcja, która wykonuje przejście

class fromViewController : UIViewController { 
    let transitionManager = TransitionManager() 

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

Następnie TransitionManager wygląda następująco:

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

Nie działa. W przypadku 'self.presenting == false' pojawia się czarny ekran z niewłaściwą ramką. – Barry

+0

@ Bariera Działa to dla mnie, nie używając selingów zamiast manualnych przejść pomiędzy kontrolerami w różnych scenorysach. Patrząc na kod, który napisałeś powyżej, jesteś próbuje zastąpić przejście push kontrolera UINavigationController. Czy w zestawie scenografii masz przesunięcie, a nie prezentację? –

1

Po X> = 4 godziny pracy, to działa bez "rozdarcie" lub inne artefakty tła:

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 
      } 
     }) 
    } 
} 

Następnie w 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 
    } 
} 

Zakłada aplikacja jest przy użyciu domyślnego storyboard z początkowym VC jako UINavigationController

Powiązane problemy