代码之家  ›  专栏  ›  技术社区  ›  Fogmeister

转换为uinavigationcontroller子级时出现奇怪的导航栏动画

  •  3
  • Fogmeister  · 技术社区  · 7 年前

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

    唯一的文件就是这个…

    简短的代码位

    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 .

    炫耀绿色 过渡到A ui导航控制器 绿色背景和 多恩 目标按钮 炫蓝 .

    我所期待的

    我所期望的(以及我想要发生的)是导航栏在不调整大小的情况下交叉溶解在适当的位置。

    问题的动画

    问题是,在动画转换期间,导航栏对它有一个奇怪的动画。你可以在这里看到…

    enter image description here

    关于这一点的苹果文档

    所有的代码都是完全按照苹果文档中关于将子视图控制器添加到自定义容器视图控制器… https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html

    我试过的东西

    我也尝试过使用自动布局约束,而不是直接设置视图的框架,但这并没有改变任何东西。

    我试过跑步 view.setNeedsLayout 然后 view.layoutIfNeeded() 在新的视图控制器上 view 但这似乎也没有解决问题。

    如果子级不是uinavigationController,则没有奇怪的动画

    真正奇怪的是,如果您使用任何其他类型的视图控制器(除了 ui导航控制器 )这样动画故障就不会发生了。例如:如果其中一个视图控制器是 UITabBarController 然后这些选项卡就没有这种奇怪的动画了。更奇怪的是,如果标签中包含 ui导航控制器 然后它也没有这个动画。如果直系儿童是一个 ui导航控制器 .

    以前有人经历过吗?你有没有设法阻止这种奇怪的动画?

    1 回复  |  直到 7 年前
        1
  •  5
  •   PDA Monkey    7 年前

    如果将转换代码放在 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()