Ios 在动画视图上设置层动画
在我的一个视图上设置图层动画时遇到问题。我用谷歌搜索了这个问题,但只使用Ios 在动画视图上设置层动画,ios,swift,animation,Ios,Swift,Animation,在我的一个视图上设置图层动画时遇到问题。我用谷歌搜索了这个问题,但只使用CATransaction找到了答案,它假设我知道fromValue和toValue的范围。我在表格标题中有一个视图,单击该视图可调整自身大小。此视图是一个普通的ui视图,其动画效果与ui视图.animate()-块中的预期效果相同。此视图有一个子层CAGradientLayer,为其提供渐变背景色。当视图设置其高度的动画时,层不会随之设置动画。动画开始时,层立即更改其边界 为了确保图层整体大小正确(在初始化/加载/屏幕旋转
CATransaction
找到了答案,它假设我知道fromValue
和toValue
的范围。我在表格标题中有一个视图,单击该视图可调整自身大小。此视图是一个普通的ui视图
,其动画效果与ui视图.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()
})
这非常有效,但是我假设layoutfneed()
在某个时候调用layoutSubviews
,我假设这会破坏我添加到块中的任何CALayer动画
如您所见,我只更改视图内部视图上约束集的常数,因此我实际上不知道动画完成时实际标题视图的大小。我可能会做一些数学来计算它会是什么,但这似乎没有必要
没有更好的方法可以做到这一点吗?您需要删除CALayer
添加此代码
gradientLayer.actions = ["position": NSNull(),"frame":NSNull(),"bounds":NSNull()]
在动画过程中,有很多方法可以更新子层的帧
,但最优雅的解决方案是让UIKit
为您解决这个问题。创建一个子类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在为视图设置动画时处理层的动画
这将解决什么问题?它会使我的图层自动与UIView.animate-code一起工作,还是会使我的图层自己的CATTransaction动画与UIView.animate一起工作?这很有魅力,谢谢!但我不太清楚为什么。发生了什么事?UIView中的原始CALayer是否具有内置逻辑,而您实际上制作了一个UIView,其中原始CALayer是一个CAGradientLayer,这给了它所有的魔力?我最初认为是这样,但当我试图设置self.layer=gradientLayer时,我被告知self.layer是只读的。您的解决方案非常出色。是的,您不能在事后使用self.layer=gradientLayer
更改图层,而是指定layerClass
,以便UIKit同时执行原始实例化和动画。一旦熟悉了这项技术,它实际上会更容易,但它不是很明显,是吗?这是天才!Thanks@iVentis不,这不适用于CAShapeLayer
,因为您需要更新路径。选项包括CABasicAnimation
或CADisplayLink
驱动动画。最简单的选项是在绘制(:)
方法中渲染边框(并使用的内容模式
。重画
)。。。笔划不是完美的中间动画,但如果动画相当短,没有人会注意到。但是,所有这些都超出了这个问题的范围,我建议你发布你自己的…@Rob谢谢你的快速回答!我通过使用相同的动画选项设置层的动画解决了这个问题。