RootViewController切换转换animation

有什么办法有一个过渡/animation效果,而用一个新的appDelegatereplace现有的viewcontroller作为rootviewcontroller?

当然。 只需将rootViewController的切换包装在一个转换块中即可:

 [UIView transitionWithView:self.window duration:0.5 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{ self.window.rootViewController = newViewController; } completion:nil]; 

我发现这一点,并完美的作品:

在你的appDelegate中:

 - (void)changeRootViewController:(UIViewController*)viewController { if (!self.window.rootViewController) { self.window.rootViewController = viewController; return; } UIView *snapShot = [self.window snapshotViewAfterScreenUpdates:YES]; [viewController.view addSubview:snapShot]; self.window.rootViewController = viewController; [UIView animateWithDuration:0.5 animations:^{ snapShot.layer.opacity = 0; snapShot.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5); } completion:^(BOOL finished) { [snapShot removeFromSuperview]; }]; } 

在你的应用程序

  if (!app) { app = (AppDelegate *)[[UIApplication sharedApplication] delegate]; } [app changeRootViewController:newViewController]; 

积分:

https://gist.github.com/gimenete/53704124583b5df3b407

我张贴耶稣答复快速实施。 它将viewcontroller的标识符作为参数,从storyboard desiredViewController加载,并用animation改变rootViewController。

Swift 3.0更新:

  func changeRootViewController(with identifier:String!) { let storyboard = self.window?.rootViewController?.storyboard let desiredViewController = storyboard?.instantiateViewController(withIdentifier: identifier); let snapshot:UIView = (self.window?.snapshotView(afterScreenUpdates: true))! desiredViewController?.view.addSubview(snapshot); self.window?.rootViewController = desiredViewController; UIView.animate(withDuration: 0.3, animations: {() in snapshot.layer.opacity = 0; snapshot.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5); }, completion: { (value: Bool) in snapshot.removeFromSuperview(); }); } 

Swift 2.2更新:

  func changeRootViewControllerWithIdentifier(identifier:String!) { let storyboard = self.window?.rootViewController?.storyboard let desiredViewController = storyboard?.instantiateViewControllerWithIdentifier(identifier); let snapshot:UIView = (self.window?.snapshotViewAfterScreenUpdates(true))! desiredViewController?.view.addSubview(snapshot); self.window?.rootViewController = desiredViewController; UIView.animateWithDuration(0.3, animations: {() in snapshot.layer.opacity = 0; snapshot.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5); }, completion: { (value: Bool) in snapshot.removeFromSuperview(); }); } class func sharedAppDelegate() -> AppDelegate? { return UIApplication.sharedApplication().delegate as? AppDelegate; } 

之后,你从任何地方都有一个非常简单的用法:

 let appDelegate = AppDelegate.sharedAppDelegate() appDelegate?.changeRootViewControllerWithIdentifier("YourViewControllerID") 

Swift 3.0更新

 let appDelegate = UIApplication.shared.delegate as! AppDelegate appDelegate.changeRootViewController(with: "listenViewController") 

//快速:

 UIView.transitionWithView(self.window!, duration: 0.5, options: UIViewAnimationOptions.TransitionFlipFromLeft, animations: { self.window?.rootViewController = anyViewController }, completion: nil) 

试试这个吧 为我工作得很好。

 BOOL oldState = [UIView areAnimationsEnabled]; [UIView setAnimationsEnabled:NO]; self.window.rootViewController = viewController; [UIView transitionWithView:self.window duration:0.5 options:transition animations:^{ // } completion:^(BOOL finished) { [UIView setAnimationsEnabled:oldState]; }]; 

编辑:

这一个更好。

 - (void)setRootViewController:(UIViewController *)viewController withTransition:(UIViewAnimationOptions)transition completion:(void (^)(BOOL finished))completion { UIViewController *oldViewController = self.window.rootViewController; [UIView transitionFromView:oldViewController.view toView:viewController.view duration:0.5f options:(UIViewAnimationOptions)(transition|UIViewAnimationOptionAllowAnimatedContent|UIViewAnimationOptionLayoutSubviews) completion:^(BOOL finished) { self.window.rootViewController = viewController; if (completion) { completion(finished); } }]; } 

为了不在转换过程中出现问题,稍后在应用程序中清除旧视图也是很好的select

 UIViewController *oldController=self.window.rootViewController; [UIView transitionWithView:self.window duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ self.window.rootViewController = nav; } completion:^(BOOL finished) { if(oldController!=nil) [oldController.view removeFromSuperview]; }]; 

在AppDelegate.h中:

 #define ApplicationDelegate ((AppDelegate *)[UIApplication sharedApplication].delegate)] 

在你的控制器中:

 [UIView transitionWithView:self.window duration:0.5 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{ ApplicationDelegate.window.rootViewController = newViewController; } completion:nil]; 

正确的答案是你不需要replace你的窗口上的rootViewController 。 相反,创build一个自定义UIViewController ,分配一次,让它显示一个孩子控制器,并根据需要replaceanimation。 您可以使用下面的一段代码作为起点:

Swift 3.0

 import Foundation import UIKit /// Displays a single child controller at a time. /// Replaces the current child controller optionally with animation. class FrameViewController: UIViewController { private(set) var displayedViewController: UIViewController? func display(_ viewController: UIViewController, animated: Bool = false) { addChildViewController(viewController) let oldViewController = displayedViewController view.addSubview(viewController.view) viewController.view.layoutIfNeeded() let finishDisplay: (Bool) -> Void = { [weak self] finished in if !finished { return } oldViewController?.view.removeFromSuperview() oldViewController?.removeFromParentViewController() viewController.didMove(toParentViewController: self) } if (animated) { viewController.view.alpha = 0 UIView.animate( withDuration: 0.5, animations: { viewController.view.alpha = 1; oldViewController?.view.alpha = 0 }, completion: finishDisplay ) } else { finishDisplay(true) } displayedViewController = viewController } override var preferredStatusBarStyle: UIStatusBarStyle { return displayedViewController?.preferredStatusBarStyle ?? .default } } 

而你使用它的方式是:

 ... let rootController = FrameViewController() rootController.display(UINavigationController(rootViewController: MyController())) window.rootViewController = rootController window.makeKeyAndVisible() ... 

上面的例子演示了你可以嵌套在FrameViewController UINavigationController ,并且工作得很好。 这种方法为您提供高水平的定制和控制。 只要调用FrameViewController.display(_)任何时候你想要replace窗口上的根控制器,它会为你做这个工作。

这是swift 3的更新,这个方法应该在你的应用程序委托中,并且你可以从任何视图控制器通过应用程序委托的共享实例

 func logOutAnimation() { let storyBoard = UIStoryboard.init(name: "SignIn", bundle: nil) let viewController = storyBoard.instantiateViewController(withIdentifier: "signInVC") UIView.transition(with: self.window!, duration: 0.5, options: UIViewAnimationOptions.transitionFlipFromLeft, animations: { self.window?.rootViewController = viewController self.window?.makeKeyAndVisible() }, completion: nil) } 

以上各种问题中缺less的部分是

  self.window?.makeKeyAndVisible() 

希望这有助于某人。