使用容器视图控制器,如何在子视图控制器之间添加交互式动画?

Posted

技术标签:

【中文标题】使用容器视图控制器,如何在子视图控制器之间添加交互式动画?【英文标题】:Using a ContainerViewController, how do i add an interactive animation between child ViewControllers? 【发布时间】:2018-01-18 19:14:30 【问题描述】:

我正在尝试创建一个自定义的NavigationViewController,其中导航栏是顶部的可滑动栏,用于控制转换(想想UITabBarController,但使用滑动手势而不是按钮)。 Here is a quick mockup. I apologize for the crudeness

我将标题栏设置为 ScrollView。我已经能够使用scrollViewDidScroll 方法成功检测到滚动量。所以我已经安装了标题栏部分。我现在需要在scrollViewDidScroll 方法中实现过渡运动。

我查看了Apple Documentation,了解如何将视图控制器相互嵌入,但它并没有真正帮助解释如何做到这一点。文档提到调用 addChildViewController: 方法和一堆其他方法,如果我想让 viewController 立即消失并重新出现,这些方法很好,但在这种情况下,我发现很难以交互方式完成。

我是否创建当前 VC 的快照然后移动它?但那我到底在移动什么?例如,在图片中,我是否将整个 RedVC 向左移动?但是,如果 BlueVC 从框架外开始移动,我如何获得它的快照呢?如果我想在 BlueVC 中异步加载图像怎么办?在 BlueVC 卡到位之前,我是否必须使用占位符快照和占位符?

这一切都变得如此令人费解......我已经单独完成了这样的事情(快照、自定义 VC 转换等),但在这样的情况下将它们全部组合在一起我还不够舒服。我确信只要有足够的时间,我就能搞定一些方法,但我想了解什么是最好、最干净的方法。

感谢您的帮助!谢谢。

接受@MilanNosáľ 的回答后编辑:

我最终使用了this repo 中链接的他的框架。它还不是交互式的,但我可以使用他们为我所做的非常友好的事情来弄清楚其余的部分。我希望我可以在这里发布完整的代码,但这不是很实用。对于未来的 SO 旅行者,该 repo 将无限期保留。

【问题讨论】:

我要厚颜无耻地宣传我自己的开源项目,我在其中从事类似的任务.. 所以请随意从那里获得灵感,甚至贡献:github.com/MilanNosal/InteractiveTransitioningContainer跨度> 这可能是我正在寻找的。它是干净的、交互式的和可扩展的。我需要几个小时来深入研究它并对其进行自定义,但我会在尝试后立即编辑此评论! 花了好几个小时来深入挖掘以重新创建大部分功能。我绝对建议阅读我在其中提到的那些文章(如果你还没有的话)。我要补充一点评论作为答案,只是为了获得更多的推广:) @MilanNosáľ 正在阅读它们! 可以分享上面的部分吗? 【参考方案1】:

我将无耻地宣传我自己的开源项目,我在其中处理类似的任务 - InteractiveTransitioningContainer。它的目标是准备一个框架来实现自定义容器,允许其子控制器之间的交互转换。虽然这可能不是问题的直接答案,但我花了很多时间尝试为子控制器提供与标准容器相同的环境 - 例如,确保按正确的顺序调用它们的 view(Will|Did)(A|Disa)ppear 回调 - 我不得不进行实验用UINavigationController分析其行为等

所以如果不出意外,也许你会在那里找到一些灵感/知识。

【讨论】:

嘿,所以我一直在尝试了解您链接的 InteractiveTransitioningContainer 的实现,但不幸的是我不太了解它是如何工作的。我需要改变什么才能让它像我上面提到的那样工作?目前我能做的最好的是将它添加到项目的 AppDelegate 并让它控制整个屏幕,这不是我想要的。我只希望它位于控制它的标题栏下方(就像在模型中一样) 如果您能解释一下文件结构以及每个文件的作用,那将会很有帮助。该代码几乎没有 cmets,因此很难遵循 @QuantumHoneybees 我希望我能在周日完成。示例中使用的SwipeToSlideAutolayoutInteractiveTransitioningContainer 是自定义容器的具体实现——在这种情况下与UIPageViewController 非常相似——在你的情况下,你想使用SwipeToSlideAutolayoutInteractiveTransitioningContainer,或者更好的是它的超类——SwipeToSlideInteractiveTransitioningContainer——作为为您自己的容器提供灵感。看看你的模型,我认为我们应该能够实现它。抱歉,我要到星期天才能开始。 那么我需要的是根据我的需要用我自己的实现替换 SwipeToSlideImpl 文件夹中的所有内容? @QuantumHoneybees 我相信你想要的是继承InteractiveTransitioningContainer(就像SwipeToSlideInteractiveTransitioningContainer 所做的那样),并实现InteractiveTransitioningContainer 工作所需的所有其他组件。我不有信心告诉你确切的步骤,因为我上次贡献它已经几个月了,但如果你能等到周末,我相信我应该能够创建一个你想要的基本模型【参考方案2】:

您真正需要的是创建自定义 segue 以从当前 VC 移动到目标 VC 并覆盖这样的执行方法,在此代码中 sn-p 当前 VC 向上移动并且目标动画从底部到顶部,随意更改任何方式

    override func perform() 
        // Assign the source and destination views to local variables.
        var firstVCView = self.sourceViewController.view as UIView!
        var secondVCView = self.destinationViewController.view as UIView!

        // Get the screen width and height.
        let screenWidth = UIScreen.mainScreen().bounds.size.width
        let screenHeight = UIScreen.mainScreen().bounds.size.height

        // Specify the initial position of the destination view.
        secondVCView.frame = CGRectMake(0.0, screenHeight, screenWidth, screenHeight)

        // Access the app's key window and insert the destination view above the current (source) one.
        let window = UIApplication.sharedApplication().keyWindow
        window?.insertSubview(secondVCView, aboveSubview: firstVCView)

        // Animate the transition.
        UIView.animateWithDuration(0.4, animations:  () -> Void in
            firstVCView.frame = CGRectOffset(firstVCView.frame, 0.0, -screenHeight)
            secondVCView.frame = CGRectOffset(secondVCView.frame, 0.0, -screenHeight)

            )  (Finished) -> Void in
                self.sourceViewController.presentViewController(self.destinationViewController as UIViewController,
                    animated: false,
                    completion: nil)
        

    

查看更多信息在这里custom-segue-animations

【讨论】:

感谢您的回复,但我该如何添加交互性呢?这似乎是一个设置动画,当我在两个视图控制器之间切换时触发,这不是我在这种情况下要寻找的 交互性是什么意思?? 我的意思是我想把它装配起来,这样当用户向左滑动标题栏时,子 VC 也向左滑动,新的 VC 开始显示。但是如果用户不松开滑动,他仍然可以在没有完全segued的情况下回到旧的VC。 你可以试试pageViewController【参考方案3】:

我最初选择米兰的答案作为该问题的最终答案。但是,在过去几周我尝试处理它之后,在他很多的帮助下,我们都同意将他的框架集成到可用于此任务的格式中太难了。我现在正在为下面的 ViewControllers 使用 UIScrollView,并让上面的 HeaderView(带有标签的东西)控制下面的 ViewControllers 的滚动视图。

【讨论】:

以上是关于使用容器视图控制器,如何在子视图控制器之间添加交互式动画?的主要内容,如果未能解决你的问题,请参考以下文章

管理容器视图控制器内同级视图控制器之间的交互

添加子视图会在子视图和导航栏之间留下空隙

UIButton 在子视图控制器中不起作用

如何在容器视图和主视图控制器之间正确传递数据

将导航控制器栏按钮与嵌入容器视图交互

如何使用 swift 在子视图中添加标签栏和导航栏?