动画UIView上的动画层

Sti*_*Sti 3 animation ios swift

我在为其中一个视图设置动画时遇到麻烦。我已经用谷歌搜索了这个问题,但是仅在CATransaction假定我知道fromValuetoValue的范围内才能找到答案。我有一个视图,该视图在tableHeader单击时会自动调整大小。此视图是普通视图,UIView并且与-block一样具有动画效果UIView.animate()。此视图具有一个CAGradientLayer作为子层,以为其提供渐变backgroundcolor。当视图为其高度设置动画时,该图层不会为其设置动画。动画开始时,图层立即更改其边界。

为了确保该层总体上具有正确的尺寸(在初始化/加载/屏幕旋转等过程中),我被告知要这样做:

override func layoutSubviews() {
    super.layoutSubviews()
    gradientLayer.frame = backgroundView.bounds
}
Run Code Online (Sandbox Code Playgroud)

每次都获得正确的尺寸,但是它永远不会动起来。

要进行视图动画,请执行以下操作:

self.someLabelHeightConstraint.constant = someHeight
UIView.animate(withDuration: 0.3, animations: { [weak self] in                
    self?.layoutIfNeeded()
})
Run Code Online (Sandbox Code Playgroud)

效果很好,但是我假设在某个时候会layoutIfNeeded()调用layoutSubviews,这会破坏我添加到模块中的所有CALayer动画。

如您所见,我只更改视图内部视图上约束集的常量,因此实际上我不知道动画完成后实际标题视图的大小。我可能可以做一些数学运算来弄清楚它是什么,但这似乎是不必要的。

有没有更好的方法可以做到这一点?

Rob*_*Rob 6

有多种灵活的方法可以frame在动画过程中更新子图层,但是最优雅的解决方案是让您UIKit自己解决这一问题。创建一个子类,UIViewlayerClassCAGradientLayer。创建视图后,CAGradientLayer将为您创建视图。当您为视图的帧设置动画时,渐变层会为您优雅地设置动画。

@IBDesignable
public class GradientView: UIView {

    @IBInspectable public var startColor: UIColor = .white { didSet { updateColors() } }
    @IBInspectable public var endColor:   UIColor = .black { didSet { updateColors() } }

    override open class var layerClass: AnyClass { return CAGradientLayer.self }

    override public init(frame: CGRect = .zero) {
        super.init(frame: frame)
        config()
    }

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        config()
    }

    private func config() {
        updateColors()
    }

    private func updateColors() {
        let gradientLayer = layer as! CAGradientLayer

        gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
    }

}
Run Code Online (Sandbox Code Playgroud)

注意,我已经这样@IBDesignable做了,因此您可以将其放在框架目标中,然后在IB中使用它,但这取决于您。这不是必需的。主要问题是的覆盖,layerClass以便UIKit在对视图进行动画处理时负责图层的动画处理。

在此处输入图片说明

  • @Rob 感谢您的快速回答!我通过使用相同的动画选项对图层进行动画处理来解决这个问题。https://medium.com/@maxcampolo/animating-uiview-sublayers-fa549e82cbbd (2认同)