转换到 child UINavigationController 时奇怪的导航栏动画
Strange navigation bar animation when transitioning to a child UINavigationController
我创建了一个小项目来重现这个问题。
唯一的文件是这个...
一小段代码
class RootViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
showBlue()
}
@objc func showBlue() {
let vc = UIViewController()
vc.view.backgroundColor = .blue
let nvc = UINavigationController(rootViewController: vc)
vc.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(showGreen))
transition(to: nvc)
}
@objc func showGreen() {
let vc = UIViewController()
vc.view.backgroundColor = .green
let nvc = UINavigationController(rootViewController: vc)
vc.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(showBlue))
transition(to: nvc)
}
func transition(to toVC: UIViewController) {
if let fromVC = children.first {
transitionWithAnimation(fromVC: fromVC, toVC: toVC)
} else {
addWithoutAnimation(child: toVC)
}
}
func addWithoutAnimation(child toVC: UIViewController) {
addChild(toVC)
view.addSubview(toVC.view)
toVC.view.frame = view.bounds
toVC.didMove(toParent: self)
}
func transitionWithAnimation(fromVC: UIViewController, toVC: UIViewController) {
addChild(toVC)
toVC.view.frame = view.bounds
fromVC.willMove(toParent: nil)
transition(
from: fromVC,
to: toVC,
duration: 1.0,
options: .transitionCrossDissolve,
animations: nil) { _ in
fromVC.removeFromParent()
toVC.didMove(toParent: self)
}
}
}
解释代码
RootViewController 首先做 showBlue
。这会添加一个 child UINavigationController
和一个带有蓝色背景的 rootViewController
。蓝色视图控制器有一个 Done
按钮,然后指向 showGreen
.
showGreen
过渡到具有绿色背景和目标 showBlue
.
的 Done
按钮的 UINavigationController
如我所料
我期望(以及我想要发生的)是导航栏在不调整大小的情况下交叉溶解到位。
问题动画
问题是在动画过渡期间,导航栏有一个奇怪的动画。你可以在这里看到...
关于此的 Apple 文档
所有代码都完全遵循关于将 child 视图控制器添加到自定义容器视图控制器的 Apple 文档... https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html
我尝试过的事情
我也尝试过使用 AutoLayout 约束而不是直接设置视图的框架,但这并没有改变任何东西。
我在新视图控制器的 view
上尝试了 运行 view.setNeedsLayout
然后 view.layoutIfNeeded()
但这似乎也没有解决它。
如果child不是UINavigationController
就没有奇怪的动画
真正奇怪的是,如果您使用任何其他类型的视图控制器(UINavigationController
除外),则不会发生此动画故障。例如:如果其中一个视图控制器是 UITabBarController
那么选项卡就没有这种奇怪的动画。更奇怪的是,如果选项卡包含 UINavigationController
那么它也没有这个动画。从字面上看,如果直接 child 是 UINavigationController
.
有没有人遇到过这种情况?你有没有设法阻止奇怪的动画?
如果将转换代码放在 CATransaction
中并使用 kCATransactionDisableActions
键关闭隐式操作,它将解决问题:
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey:kCATransactionDisableActions)
transition(
from: fromVC,
to: toVC,
duration: 1.0,
options: [.transitionCrossDissolve],
animations: nil) { _ in
fromVC.removeFromParent()
toVC.didMove(toParent: self)
}
CATransaction.commit()
我创建了一个小项目来重现这个问题。
唯一的文件是这个...
一小段代码
class RootViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
showBlue()
}
@objc func showBlue() {
let vc = UIViewController()
vc.view.backgroundColor = .blue
let nvc = UINavigationController(rootViewController: vc)
vc.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(showGreen))
transition(to: nvc)
}
@objc func showGreen() {
let vc = UIViewController()
vc.view.backgroundColor = .green
let nvc = UINavigationController(rootViewController: vc)
vc.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(showBlue))
transition(to: nvc)
}
func transition(to toVC: UIViewController) {
if let fromVC = children.first {
transitionWithAnimation(fromVC: fromVC, toVC: toVC)
} else {
addWithoutAnimation(child: toVC)
}
}
func addWithoutAnimation(child toVC: UIViewController) {
addChild(toVC)
view.addSubview(toVC.view)
toVC.view.frame = view.bounds
toVC.didMove(toParent: self)
}
func transitionWithAnimation(fromVC: UIViewController, toVC: UIViewController) {
addChild(toVC)
toVC.view.frame = view.bounds
fromVC.willMove(toParent: nil)
transition(
from: fromVC,
to: toVC,
duration: 1.0,
options: .transitionCrossDissolve,
animations: nil) { _ in
fromVC.removeFromParent()
toVC.didMove(toParent: self)
}
}
}
解释代码
RootViewController 首先做 showBlue
。这会添加一个 child UINavigationController
和一个带有蓝色背景的 rootViewController
。蓝色视图控制器有一个 Done
按钮,然后指向 showGreen
.
showGreen
过渡到具有绿色背景和目标 showBlue
.
Done
按钮的 UINavigationController
如我所料
我期望(以及我想要发生的)是导航栏在不调整大小的情况下交叉溶解到位。
问题动画
问题是在动画过渡期间,导航栏有一个奇怪的动画。你可以在这里看到...
关于此的 Apple 文档
所有代码都完全遵循关于将 child 视图控制器添加到自定义容器视图控制器的 Apple 文档... https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html
我尝试过的事情
我也尝试过使用 AutoLayout 约束而不是直接设置视图的框架,但这并没有改变任何东西。
我在新视图控制器的 view
上尝试了 运行 view.setNeedsLayout
然后 view.layoutIfNeeded()
但这似乎也没有解决它。
如果child不是UINavigationController
就没有奇怪的动画真正奇怪的是,如果您使用任何其他类型的视图控制器(UINavigationController
除外),则不会发生此动画故障。例如:如果其中一个视图控制器是 UITabBarController
那么选项卡就没有这种奇怪的动画。更奇怪的是,如果选项卡包含 UINavigationController
那么它也没有这个动画。从字面上看,如果直接 child 是 UINavigationController
.
有没有人遇到过这种情况?你有没有设法阻止奇怪的动画?
如果将转换代码放在 CATransaction
中并使用 kCATransactionDisableActions
键关闭隐式操作,它将解决问题:
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey:kCATransactionDisableActions)
transition(
from: fromVC,
to: toVC,
duration: 1.0,
options: [.transitionCrossDissolve],
animations: nil) { _ in
fromVC.removeFromParent()
toVC.didMove(toParent: self)
}
CATransaction.commit()