同步视图交叉溶解的动画布局更改

时间:2018-03-21 07:33:01

标签: ios uiview uiviewanimation

我有一个UIView,其中包含一些使用AutoLayout定位的UILabel

在设备旋转时,我切换布局约束以将标签设置为新位置(布局约束来自分配给视图的Layout对象):

override func viewWillTransition(
  to size: CGSize, 
  with coordinator: UIViewControllerTransitionCoordinator
) {
    super.viewWillTransition(to: size, with: coordinator)
    let isLandscape = size.width > size.height
    let layout = isLandscape ? layoutLandscape : layoutPortrait

    coordinator.animate(
        alongsideTransition: { _ in self.layoutView.setLayout(layout) },
        completion: nil
    )
}

此效果效果很好,可在针对横向和纵向优化的不同内容布局之间提供平滑过渡。

但是,在转换期间,标签的 size 也会因布局限制而发生变化。值得注意的是,虽然标签位置的过渡是渐进的,但标签的形状会在过渡开始时立即发生变化,然后它们会动画到最终位置。

我希望能够在初始和最终形状之间交叉分解标签,并将其与位置动画一起发生。

理想情况下,我希望以相同的高度分离方式实现这一点,即实现位置动画,布局更新代码不知道更改是否会被动画化。我希望至少可能需要一些折衷方案!

谢谢。

我非常接近这方面的工作解决方案。它还没有回答材料,所以我要在这里写下“我试过的东西” - 如果它成为一个答案,我会把它变成一个。

fantastic article at objc.io显示了如何创建UILabel子类,告诉其支持CALayer使用content为其CATransition属性设置动画的动画。这是最纯粹的纯粹巫术,但奇妙的是,它实际上都是有道理的,你怀疑也许你也可以戴巫师的帽子。

所以,你最终会得到类似的东西:

class ContentAnimatedLabel: UILabel {
    override func action(for layer: CALayer, forKey event: String) -> CAAction? {
        guard event == "contents" else {
            return super.action(for: layer, forKey: event)
        }

        let transition = CATransition()
        // Oh noes! A hard coded made up value!
        // And where do we get the timing curve?! Curses.
        transition.duration = 0.3
        return transition
    }
}

就目前而言,它有效!标签的内容很好地消失,并且它们的位置进行插值。它看起来相当宏伟。

问题是你这个代码不知道它是否是从动画块中调用的。实际上,它应该只在从动画块中调用时返回转换,它应该从动画块给出的动画属性中复制动画属性,例如持续时间和时间。

文章建议解决这个问题......

  

UIView动画机制实现是私有的,因此没有简单的标志我们可以检查视图当前是否是动画,但我们确实知道一件事:当动画时,UIView的actionForLayer:forKey:将为其动画返回有效的CAActions属性键,当没有动画时,它将为它们返回[NSNull null]。如果我们只是选择一个合适的密钥,我们可以询问UIView以查看它是否正在为该密钥提供操作,并使用它来确定我们对自定义密钥的响应。我们将使用键“backgroundColor”,因为这是通常支持动画的UIView的属性,并且我们知道返回CABasicAnimation作为其动作(从iOS 8开始,一些属性,例如“bounds”返回私有类,所以小心):

...但这似乎不起作用,至少对于我正在测试的iOS 11。

UIKit请求content键的操作时,就像动画块已完成一样。向super询问其他键使用的操作始终不返回任何内容。因此,您无需从中获取适当的转换参数。

0 个答案:

没有答案