过渡到子UINavigationController时奇怪的导航栏动画

时间:2019-01-25 11:23:50

标签: ios swift uicontainerview childviewcontroller

我创建了一个小项目来复制此问题。

唯一的文件是这个文件...

简短的代码

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。这样会添加一个带有UINavigationController且背景为蓝色的孩子rootViewController。蓝色视图控制器具有一个Done按钮,然后将其定位到showGreen

showGreen转换为带有绿色背景的UINavigationController和以Done为目标的showBlue按钮。

我所期望的

我期望(以及我想发生的事情)是导航栏可以交叉溶解而不改变大小。

问题的动画处理

问题在于,在动画过渡期间,导航栏具有奇怪的动画。您可以在这里看到...

enter image description here

关于此的Apple文档

Apple文档中完全遵循了有关将子视图控制器添加到自定义容器视图控制器中的所有代码... https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html

我尝试过的事情

我也尝试过使用AutoLayout约束,而不是直接设置视图的框架,但这没有任何改变。

我尝试在新的视图控制器的view.setNeedsLayout上运行view.layoutIfNeeded(),然后运行view,但这似乎也没有解决。

如果孩子不是UINavigationController,没有奇怪的动画

真正奇怪的是,如果您使用任何其他类型的视图控制器(UINavigationController除外),则不会发生此动画故障。例如:如果视图控制器之一是UITabBarController,则选项卡没有这种奇特的动画。甚至更陌生的是,如果选项卡包含UINavigationController,则它也没有此动画。从字面上看,直子是UINavigationController

有人曾经历过吗?并且您设法停止了奇怪的动画吗?

1 个答案:

答案 0 :(得分:5)

如果将转换代码放在CATransation中,然后使用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()