有什么方法可以在将现有的viewcontroller替换为rootviewcontroller并使用appDelegate中的新视频时获得过渡/动画效果吗?
答案 0 :(得分:270)
您可以在转换动画块中包裹rootViewController
的切换:
[UIView transitionWithView:self.window
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{ self.window.rootViewController = newViewController; }
completion:nil];
答案 1 :(得分:65)
我发现了这个并且运作得很好:
你的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];
币:
答案 2 :(得分:38)
我发布了在swift中实现的耶稣答案。它将viewcontroller的标识符作为参数,从storyboard desiredViewController加载并使用动画更改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")
答案 3 :(得分:20)
//在swift中:
UIView.transitionWithView(self.window!, duration: 0.5, options: UIViewAnimationOptions.TransitionFlipFromLeft, animations: {
self.window?.rootViewController = anyViewController
}, completion: nil)
答案 4 :(得分:10)
试试吧。对我来说很好。
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);
}
}];
}
答案 5 :(得分:3)
为了避免在应用程序中稍后出现转换翻转问题,最好从堆栈中清除旧视图
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];
}];
答案 6 :(得分:2)
正确答案是您无需更换窗口上的rootViewController
。相反,创建一个自定义UIViewController
,分配一次,让它一次显示一个子控制器,并在需要时用动画替换它。您可以使用以下代码作为起点:
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()
...
上面的示例演示了您可以在UINavigationController
内嵌套FrameViewController
,这样就可以了。这种方法为您提供高水平的定制和控制。只要您想要替换窗口上的根控制器,就可以调用FrameViewController.display(_)
,它将为您完成这项工作。
答案 7 :(得分:2)
这是swift 3的更新,此方法应该在您的app委托中,并且您可以通过应用委托的共享实例从任何视图控制器调用它
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)
}
上述各种问题中缺少的部分是
self.window?.makeKeyAndVisible()
希望这有助于某人。
答案 8 :(得分:1)
:
#define ApplicationDelegate ((AppDelegate *)[UIApplication sharedApplication].delegate)]
控制器中的:
[UIView transitionWithView:self.window
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
ApplicationDelegate.window.rootViewController = newViewController;
}
completion:nil];
答案 9 :(得分:0)
我提出了我的方式,它在我的项目中工作正常,它为我提供了良好的动画。我已经测试了这篇文章中提到的其他提案,但有些提案没有按预期工作。
- (void)transitionToViewController:(UIViewController *)viewController withTransition:(UIViewAnimationOptions)transition completion:(void (^)(BOOL finished))completion {
// Reset new RootViewController to be sure that it have not presented any controllers
[viewController dismissViewControllerAnimated:NO completion:nil];
[UIView transitionWithView:self.window
duration:0.5f
options:transition
animations:^{
for (UIView *view in self.window.subviews) {
[view removeFromSuperview];
}
[self.window addSubview:viewController.view];
self.window.rootViewController = viewController;
} completion:completion];
}
答案 10 :(得分:0)
漂亮的甜蜜动画(使用Swift 4.x测试):
extension AppDelegate {
public func present(viewController: UIViewController) {
guard let window = window else { return }
UIView.transition(with: window, duration: 0.5, options: .transitionFlipFromLeft, animations: {
window.rootViewController = viewController
}, completion: nil)
}
}
使用
进行通话guard let delegate = UIApplication.shared.delegate as? AppDelegate else { return }
delegate.present(viewController: UIViewController())