同步UIView动画

我最近正在构建一个子视图控制器框架,并且在实现动画时,偶然发现了iOS开发中一个相当常见的问题。 我正在尝试同步两个动画,使它变得不那么琐碎的事情不是直接应用于核心动画,而是使用带有动画关闭功能的常规UIView动画实现的。 更糟糕的是,由于该组件是作为框架开发的,因此解决方案必须没有牢固的联系。
幸运的是,我找到了一个很想与您分享的解决方案。


为了给您更多的上下文,我正在尝试解决的问题是框架布局算法。 我想为框架的用户提供对视图层次结构的完全控制,让他们可以选择在展开,折叠或仅隐藏UI组件时应用动画。 第一步只是在动画环境中运行算法。

我采用了最直接的方法,即将算法包装在UIView动画闭包中,并为动画提供从其当前状态开始并允许用户交互的选项。 后者的添加不会破坏用户的滚动体验。

到目前为止,一切都很好,但是当我开始测试不同的场景时,我很快意识到动画是不同步的。 如果动画持续时间与框架使用的持续时间不匹配,则它们将永远不匹配。
客户端代码如下所示:

如果仔细观察,您会发现框架和客户端应用程序的持续时间是不同步的,主要是因为用户想要的值不是框架默认值。

从框架的起源出发,我想使API尽可能简单,并且比您从未学习过的东西更直接。 我以为自己遇到了障碍,将不得不实施另一种方法来正确过渡到新状态。

经过一些调查并深入思考了UIView动画是什么,我提出了一个解决方案。

UIView动画是核心动画之上的一种便利抽象,这意味着可以通过向图层询问其动画键来解决这些问题。 对于我尝试解决的情况,我可以简单地查询要监视的视图,以了解其中是否有绑定动画。

这将决定布局算法是否将使用动画运行,或者结果是否应立即呈现。

因此,在了解正在播放哪些动画关键帧的情况下,我可以提取动画并检查其值。 对于帧动画,我最终得到一个` CABasicAnimation` 。 因为CABasicAnimation继承自CAAnimation ,而CAAnimation又符合CAMediaTiming ,所以我可以使用我想要的duration属性。

我把它们全部包装在CALayer的一个小扩展中,这不是美的事,但是它可以工作。

https://github.com/zenangst/Family/blob/master/Sources/iOS%2BtvOS/Extensions/CALayer%2BExtensions.swift

就我而言,我只关心第一个动画及其持续时间,因此最终将其作为框架中的实现:

https://github.com/zenangst/Family/blob/master/Sources/iOS%2BtvOS/Classes/FamilyScrollView.swift#L250-L257

我敢打赌,大家可以将其应用到更高级的案例中,但是这种方法有助于解决我所面临的问题,希望您觉得这有用,这对我来说是大开眼界的。