Sti*_*Sti 3 animation ios swift
我在为其中一个视图设置动画时遇到麻烦。我已经用谷歌搜索了这个问题,但是仅在CATransaction假定我知道fromValue和toValue的范围内才能找到答案。我有一个视图,该视图在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动画。
如您所见,我只更改视图内部视图上约束集的常量,因此实际上我不知道动画完成后实际标题视图的大小。我可能可以做一些数学运算来弄清楚它是什么,但这似乎是不必要的。
有没有更好的方法可以做到这一点?
有多种灵活的方法可以frame在动画过程中更新子图层,但是最优雅的解决方案是让您UIKit自己解决这一问题。创建一个子类,UIView其layerClass为CAGradientLayer。创建视图后,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在对视图进行动画处理时负责图层的动画处理。