嵌入到导航控制器中的动画根视图控制器以模态方式呈现

Posted

技术标签:

【中文标题】嵌入到导航控制器中的动画根视图控制器以模态方式呈现【英文标题】:Animate root view controller embedded into a navigation controller presented modally 【发布时间】:2021-01-26 10:38:53 【问题描述】:

我需要为 UIViewController 制作动画,它是 UINavigationController 的根。该导航控制器以模态方式呈现。 我知道我可以使用视图控制器的生命周期方法来做到这一点,但如果可能的话,我想使用UIViewControllerAnimatedTransitioning 来保持 VC 代码的清洁。

我尝试了以下方法:

a) 将UINavigationControllerDelegate 设置为导航控制器,这样我就可以使用这个委托函数:

func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?

但是,它只会在导航控制器(从 VC 到 VC)的转换过程中被调用。

b) 在根视图控制器中设置UIViewControllerTransitioningDelegate 并使用此委托函数:

func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning?

但同样,它不会被调用,因为呈现的是导航控制器。

c) 在导航控制器中设置UIViewControllerTransitioningDelegate 并使用相同的委托函数:

func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning?

在这种情况下,它会被调用,我可以注入 UIViewControllerAnimatedTransitioning 对象,但我只能考虑使用 hack 来为根设置动画,例如

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) 
    guard let fromVC = transitionContext.viewController(forKey: .from),
          let toVC = transitionContext.viewController(forKey: .to) as? UINavigationController,
          toVC.children.count == 1,
          let myRootVC = toVC.children.first as? MyViewController
    else 
        transitionContext.completeTransition(false)
        return
    
    // Animate manually
    myRootVC.view.alpha = 0
    // [...]

你知道有什么方法可以很好地捕捉到这个吗?

【问题讨论】:

你想出解决方案了吗?我也坚持这个 【参考方案1】:

我通过使用 ViewController Containment 将我的所有 ViewControllers 呈现为嵌入式 ViewController 解决了类似的问题。

在启动应用程序时,我确实设置了 1 个 RootContainerViewController - 它只是设置为 rootViewController 没有动画,它只是所有其他 ViewController 的容器。

所有其他 ViewControllers 总是作为 SubViewControllers 和 SubViews 添加到该容器中。

这不仅允许您在应用程序中的每个转换中使用UIViewControllerAnimatedTransitioning,而且还允许您轻松地“重置”应用程序,只需删除RootContainerViewController 并将其替换为新的。 另一个优点是您可以根据需要添加任意数量的 ViewController - 与本机 presentViewController 相比,您一次只能显示 1 个 ViewController。

我尝试过的任何其他方法都以失败告终 - UIViewControllerAnimatedTransitioning 无法直接与 rootViewController 更改一起使用 - 您必须将其与 UIView.animate 结合使用才能支持它。

【讨论】:

我认为在这种情况下我更愿意将动画逻辑放入 VC 代码中并对其进行动画处理。在我的情况下,它是一个模态呈现的导航控制器,所以我认为我更喜欢这个而不是添加一个根容器然后从那里转换。谢谢! @jomafer 一旦你将添加更多动画然后修改视图控制器的连接方式 - 拥有自己的演示系统变得很方便;)

以上是关于嵌入到导航控制器中的动画根视图控制器以模态方式呈现的主要内容,如果未能解决你的问题,请参考以下文章

以模态方式将嵌入在导航控制器中的视图控制器与标签栏控制器分开

如何以模态方式呈现 VC,然后转到嵌入在导航控制器中的 VC

从 UINavigationVController 导航以模态方式呈现到根 UINavigationVController - swift

以模态方式呈现视图控制器时,导航栏与黑色而不是白色混合

无法关闭嵌入在导航控制器中的两个视图控制器

如何检查视图控制器是不是以模态方式呈现或推送到导航堆栈上?