用动画交换 rootViewController?
Swap rootViewController with animation?
我正在尝试切换到另一个带有标签栏的根视图控制器;通过应用程序委托,我想添加过渡动画。默认情况下,它只会显示没有任何动画的视图。
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 控制器的方式。
试试这个:
UIView.transition(from: appdelegate.window.rootViewController!.view, to: tabbar.view, duration: 0.6, options: [.transitionCrossDissolve], completion: {
_ in
appdelegate.window.rootViewController = tabbar
})
您可以使用 UIView.transition(with: view)
替换 UIWindow
的 rootViewController
:
guard let window = UIApplication.shared.keyWindow else {
return
}
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "MainTabbar")
// Set the new rootViewController of the window.
// Calling "UIView.transition" below will animate the swap.
window.rootViewController = vc
// A mask of options indicating how you want to perform the animations.
let options: UIView.AnimationOptions = .transitionCrossDissolve
// The duration of the transition animation, measured in seconds.
let duration: TimeInterval = 0.3
// Creates a transition animation.
// Though `animations` is optional, the documentation tells us that it must not be nil. ¯\_(ツ)_/¯
UIView.transition(with: window, duration: duration, options: options, animations: {}, completion:
{ completed in
// maybe do something on completion here
})
Im trying to swap to another root view controller ... and I want to add transition animation
我有一个应用程序可以执行此操作:它使用动画更改根视图控制器(称为 Albumen)。
但我的应用实际上并没有实际更改根视图控制器。根视图控制器是一个永远不会改变的自定义容器视图控制器。它的视图从未见过,也没有任何功能。它唯一的工作就是成为变化发生的地方:它将一个子视图控制器换成另一个——因此过渡动画起作用。
换句话说,您将一个视图控制器添加到您的视图控制器层次结构中,就在层次结构的顶部,整个问题就干净利落地得到了正确解决。
另一种解决方案:
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()
})
Swift 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)
}
我根据d.felber的回答为此创建了一个助手class:
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
}
已更新 Swift 5.3 版本:
let foregroundedScenes = UIApplication.shared.connectedScenes.filter { [=10=].activationState == .foregroundActive }
let window = foregroundedScenes.map { [=10=] as? UIWindowScene }.compactMap { [=10=] }.first?.windows.filter { [=10=].isKeyWindow }.first
guard let uWindow = window else { return }
uWindow.rootViewController = customTabBarController
UIView.transition(with: uWindow, duration: 0.3, options: [.transitionCrossDissolve], animations: {}, completion: nil)
}
我正在尝试切换到另一个带有标签栏的根视图控制器;通过应用程序委托,我想添加过渡动画。默认情况下,它只会显示没有任何动画的视图。
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 控制器的方式。
试试这个:
UIView.transition(from: appdelegate.window.rootViewController!.view, to: tabbar.view, duration: 0.6, options: [.transitionCrossDissolve], completion: {
_ in
appdelegate.window.rootViewController = tabbar
})
您可以使用 UIView.transition(with: view)
替换 UIWindow
的 rootViewController
:
guard let window = UIApplication.shared.keyWindow else {
return
}
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "MainTabbar")
// Set the new rootViewController of the window.
// Calling "UIView.transition" below will animate the swap.
window.rootViewController = vc
// A mask of options indicating how you want to perform the animations.
let options: UIView.AnimationOptions = .transitionCrossDissolve
// The duration of the transition animation, measured in seconds.
let duration: TimeInterval = 0.3
// Creates a transition animation.
// Though `animations` is optional, the documentation tells us that it must not be nil. ¯\_(ツ)_/¯
UIView.transition(with: window, duration: duration, options: options, animations: {}, completion:
{ completed in
// maybe do something on completion here
})
Im trying to swap to another root view controller ... and I want to add transition animation
我有一个应用程序可以执行此操作:它使用动画更改根视图控制器(称为 Albumen)。
但我的应用实际上并没有实际更改根视图控制器。根视图控制器是一个永远不会改变的自定义容器视图控制器。它的视图从未见过,也没有任何功能。它唯一的工作就是成为变化发生的地方:它将一个子视图控制器换成另一个——因此过渡动画起作用。
换句话说,您将一个视图控制器添加到您的视图控制器层次结构中,就在层次结构的顶部,整个问题就干净利落地得到了正确解决。
另一种解决方案:
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()
})
Swift 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)
}
我根据d.felber的回答为此创建了一个助手class:
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
}
已更新 Swift 5.3 版本:
let foregroundedScenes = UIApplication.shared.connectedScenes.filter { [=10=].activationState == .foregroundActive }
let window = foregroundedScenes.map { [=10=] as? UIWindowScene }.compactMap { [=10=] }.first?.windows.filter { [=10=].isKeyWindow }.first
guard let uWindow = window else { return }
uWindow.rootViewController = customTabBarController
UIView.transition(with: uWindow, duration: 0.3, options: [.transitionCrossDissolve], animations: {}, completion: nil)
}