我无法在其中一个视图上设置图层动画。我用Google搜索了问题,但只能使用CATransaction
找到答案,假设我知道其边界的fromValue
和toValue
。我在tableHeader
中有一个视图,在点击时会自行调整大小。这个视图是普通的UIView
,并且在UIView.animate()
- 块中就像预期一样动画。此视图有CAGradientLayer
作为子图层,为其提供渐变背景颜色。当视图为其高度设置动画时,该图层不会对其进行动画处理。图层在动画开始时立即改变其边界。
为了确保图层整体尺寸合适(在初始化/加载/屏幕旋转等期间),我被告知这样做:
override func layoutSubviews() {
super.layoutSubviews()
gradientLayer.frame = backgroundView.bounds
}
每次都会获得正确的大小,但它从未动画过。
要做我的视图动画,我这样做:
self.someLabelHeightConstraint.constant = someHeight
UIView.animate(withDuration: 0.3, animations: { [weak self] in
self?.layoutIfNeeded()
})
效果很好,但我假设layoutIfNeeded()
在某个时刻调用layoutSubviews
,我认为这会破坏我添加到块中的任何CALayer动画。
正如您所看到的,我只更改了视图中视图上约束集的常量,所以实际上我不知道动画完成后实际标题视图的大小。我可以做一些数学计算它会是什么,但这似乎是不必要的..
有没有更好的方法可以做到这一点?
答案 0 :(得分:6)
动画期间有更新子层frame
的方法,但最优雅的解决方案是让UIKit
为您处理这个问题。创建layerClass
为UIView
的子类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]
}
}
注意,我已经制作了这个@IBDesignable
,所以你可以把它放在一个框架目标中,然后在IB中使用它,但这取决于你。这不是必需的。主要问题是覆盖layerClass
,以便UIKit在动画视图时处理图层的动画。
答案 1 :(得分:1)
您需要删除CALayer
添加此代码
gradientLayer.actions = ["position": NSNull(),"frame":NSNull(),"bounds":NSNull()]