如何使用重叠的透明视图控制器重新创建 FaceTime 的导航视图控制器转换动画?

How to recreate FaceTime's navigation view controller transition animation with overlapping transparent view controllers?

短版:

我想重现 FaceTime 的导航过渡动画,以将透明视图控制器推送到导航堆栈上,而不会使顶部视图的内容与底部视图的内容重叠。

问题:

在标准 UINavigationController 中,推动具有透明背景的目标视图控制器会导致难看的动画:源视图控制器变暗并平移,然后弹出不存在。这是因为标准的导航推送动画假设目标视图控制器在动画结束时已经完全遮盖了源视图控制器,当目标视图控制器的背景是透明时,这个假设就被违反了。请看这个动画:

我已在 https://github.com/bgfriend0/PushVCWithClearBackground 上传了一个重现此行为的演示项目。

想要的效果:

但是,Apple 的 FaceTime 应用程序似乎能够推送具有清晰背景的视图控制器,同时屏蔽源视图控制器的内容,因此推送动画是干净的。请看这个动画:

我想重现此 FaceTime 行为,但尚未找到解决方案。

研究:

关于这个问题的文献出奇地少。我可以找到一些涉及它的问题(例如,Segue Push Animation with Clear Background is Flashing on iOS 7 and Views getting darker when are pushed on navigation controller),但没有任何解决方案可以通过重现所需的 FaceTime 效果来真正解决问题。

我在一条推文中发现了 link (https://twitter.com/b3ll/status/384114227884986368) to the Apple dev forums on this issue, but again, no solution was forthcoming: https://devforums.apple.com/message/897379#897379.

想法:

我想出的唯一可行的解​​决方案与 Caleb Davenport 在 Apple 论坛上提出的解决方案基本相同 post:

It's got to be one of three things:

(1) They are masking the left view up to the frame of the right view.

(2) They are copying the background contents into the right view while offsetting it such that the right view isn't really transparent.

(3) They are running custom view transitions.

每一个都有一定程度的优点,但它们都很复杂,我忍不住希望应该有一些方便的小标志,Apple 正在利用它来产生所需的遮罩效果.当然,即使存在这样的标志,它也可能是私有的 API...不过,我正在 post 提出这个问题,看看是否有人提出或可以提出一个优雅的解决方案来重现所需的 FaceTime 透明推送动画。

对于任何可能感兴趣的人,我确实找到了这个问题的答案,因为 Apple 在 UINavigationController_UINavigationParallaxTransition 类 上使用私有标志 clipUnderlapWhileTransitioning .

参见,例如:

https://github.com/JaviSoto/iOS8-Runtime-Headers/blob/master/Frameworks/UIKit.framework/UINavigationController.h

https://github.com/JaviSoto/iOS8-Runtime-Headers/blob/master/Frameworks/UIKit.framework/_UINavigationParallaxTransition.h

有了这个标志,我就能够完全重现 Facetime 效果了。

自然地,关于使用私有 API 的所有常见注意事项都适用于这种情况(即,对于您打算提交到 App Store 的应用,这是不允许的)。