用动画交换rootViewController?

问题描述 投票:45回答:6

我试图用标签栏交换到另一个根视图控制器;通过app委托,我想添加过渡动画。默认情况下,它只显示没有任何动画的视图。

let tabBar = self.instantiateViewController(storyBoard: "Main", viewControllerID: "MainTabbar")
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window = UIWindow(frame: UIScreen.main.bounds)
appDelegate.window?.rootViewController = tabBar
appDelegate.window?.makeKeyAndVisible()

这就是我交换到另一个rootview控制器的方式。

swift xcode swift3 uiviewanimation rootview
6个回答
134
投票

我前段时间对UIView.transition(from: view, to: view)UIView.transition(with: view)进行了评估,结果使用了这个:(但遗憾的是不记得为什么)

guard let window = UIApplication.shared.keyWindow else {
    return
}

guard let rootViewController = window.rootViewController else {
    return
}

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "MainTabbar")
vc.view.frame = rootViewController.view.frame
vc.view.layoutIfNeeded()

UIView.transition(with: window, duration: 0.3, options: .transitionCrossDissolve, animations: {
    window.rootViewController = vc
}, completion: { completed in
    // maybe do something here
})

8
投票

试试这个:

UIView.transition(from: appdelegate.window.rootViewController!.view, to: tabbar.view, duration: 0.6, options: [.transitionCrossDissolve], completion: {
    _ in
    appdelegate.window.rootViewController = tabbar
})

8
投票

我试图交换到另一个根视图控制器...我想添加过渡动画

我有一个应用程序执行此操作:它使用动画更改根视图控制器(它称为Albumen)。

但我的应用实际上并没有真正改变根视图控制器。根视图控制器是一个永远不会更改的自定义容器视图控制器。它的视图从未见过,也没有任何功能。它唯一的工作就是成为变化发生的地方:它将一个子视图控制器换成另一个 - 因此过渡动画可以工作。

换句话说,您将一个视图控制器添加到视图控制器层次结构中,就在层次结构的顶部,整个问题得到了整齐和正确的解决。


4
投票

替代解决方案:

let stb = UIStoryboard(name: "YOUR_STORYBOARD_NAME", bundle: nil)
let rootVC = stb.instantiateViewController(withIdentifier: "YOUR_TABBAR_VIEWCONTROLLER_NAME")
let snapshot = (UIApplication.shared.keyWindow?.snapshotView(afterScreenUpdates: true))!
rootVC.view.addSubview(snapshot);

UIApplication.shared.keyWindow?.rootViewController = rootVC;
UIView.transition(with: snapshot, duration: 0.4, options: .transitionCrossDissolve, animations: {
    snapshot.layer.opacity = 0;
}, completion: { (status) in
    snapshot.removeFromSuperview()
})

3
投票

斯威夫特4

粘贴功能到AppDelegate

func setRootViewController(_ vc: UIViewController, animated: Bool = true) {
    guard animated, let window = self.window else {
        self.window?.rootViewController = vc
        self.window?.makeKeyAndVisible()
        return
    }

    window.rootViewController = vc
    window.makeKeyAndVisible()
    UIView.transition(with: window,
                      duration: 0.3,
                      options: .transitionCrossDissolve,
                      animations: nil,
                      completion: nil)
}

0
投票

我根据d.felber的答案为此创建了一个帮助类:


    import UIKit

    class ViewPresenter {

        public static func replaceRootView(for viewController: UIViewController,
                                   duration: TimeInterval = 0.3,
                                   options: UIView.AnimationOptions = .transitionCrossDissolve,
                                   completion: ((Bool) -> Void)? = nil) {
            guard let window = UIApplication.shared.keyWindow else {
                return
            }

            guard let rootViewController = window.rootViewController else {
                return
            }

            viewController.view.frame = rootViewController.view.frame
            viewController.view.layoutIfNeeded()

            UIView.transition(with: window, duration: duration, options: options, animations: {
                window.rootViewController = viewController
            }, completion: completion)
        }
    }

你可以像这样使用它:

    let loginVC = SignInViewController(nibName: "SignInViewController", bundle: nil)
    ViewPresenter.replaceRootView(for: loginVC)

要么

ViewPresenter.replaceRootView(for: loginVC, duration: 0.3, options: .transitionCrossDissolve) { 
(bool) in
       // do something
}
© www.soinside.com 2019 - 2024. All rights reserved.