动画不适用于插入的 CAGradientLayer 作为子层

Animation not working on inserted CAGradientLayer as sublayer

我想在加载 viewController 时执行动画(全视图高度到 88px 高度,从下到上动画)。所以我在故事板上添加了一个 UIView(animationView),在 viewDidLoad() 中以编程方式添加渐变,并在 viewDidAppear() 中执行动画,如下所示:

override func viewDidLoad() {
        super.viewDidLoad()
        self.animationView.applyGradient(with: [UIColor(red: 0, green: 91/255, blue: 200/255, alpha: 1), UIColor(red: 0, green: 131/255, blue: 232/255, alpha: 1)])
}

override func viewDidAppear(_ animated: Bool) {

        super.viewDidAppear(animated)

        //Perform animation
        self.animationVWBottomContraint.constant = self.view.bounds.height - 88.0

        UIView.animate(withDuration: 0.75,delay: 10, options: .curveEaseIn, animations: {
            self.view.layoutIfNeeded()
        }, completion: {(_) in
            DispatchQueue.main.asyncAfter(deadline: .now()+6) {
                self.animationView.isHidden = true
            }
        }
extension UIView {

 open func applyGradient(with colours: [UIColor]) {

        //Create a gradient and apply it to the sublayer.
        let gradient = CAGradientLayer()
        gradient.frame = self.bounds
        gradient.name  = "grad1"
        gradient.colors = colours.map { [=11=].cgColor }
        gradient.startPoint = CGPoint(x: 0.0,y: 0.0)
        gradient.endPoint = CGPoint(x: 0.0,y: 1.0)
        self.layer.insertSublayer(gradient, at: 0)
    }
}

如果我们添加一个图像作为animationView的子视图来检查动画是否有效果,那么我们可以看到动画发生了。但是CAGradient图层没有任何效果。

如果我们添加 backgroundColor 而不是渐变,动画会按预期发生。

override func viewDidLoad() {
        super.viewDidLoad()
        //self.animationView.applyGradient(with: [UIColor(red: 0, green: 91/255, blue: 200/255, alpha: 1), UIColor(red: 0, green: 131/255, blue: 232/255, alpha: 1)])
      self.animationView.backgroundColor = UIColor.blue
}

这意味着新添加的子图层不会在 layoutIfNeeded() 上调整大小。因此,我试图强制调用布局或创建子类并添加渐变作为自定义初始化的一部分。

self.animationView.layer.setNeedsLayout()
or 
self.animationView.layoutIfNeeded()
or
class GradientView : UIView {
    required init?(coder: NSCoder) {
        super.init(coder:coder)
        self.customInit()
    }
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.customInit()
    }

    func animate(){
        UIView.animate(withDuration: 0.25, delay: 2, options: .curveLinear, animations: {
            self.frame.size.height = 80.0
            self.layoutIfNeeded()
        }, completion: nil)
    }

    func customInit(){

        let containerView = UIView()
        self.addSubview(containerView)
        containerView.frame = self.bounds
        self.autoresizingMask = [.flexibleHeight, .flexibleWidth]
        let gradient = CAGradientLayer()
               gradient.frame = self.bounds
               gradient.name  = "grad1"
               gradient.colors = [UIColor(red: 0, green: 91/255, blue: 200/255, alpha: 1), UIColor(red: 0, green: 131/255, blue: 232/255, alpha: 1)].map { [=13=].cgColor }
               gradient.startPoint = CGPoint(x: 0.0,y: 0.0)
               gradient.endPoint = CGPoint(x: 0.0,y: 1.0)
        containerView.layer.insertSublayer(gradient, at: 0)
    }
}

但是没有用。

我该如何解决这个问题?

提前致谢。

This means the newly added sublayer doesn't get resized on layoutIfNeeded()

当父视图 bound/frame 发生变化时,图层不会自行调整大小,例如:如果您将阴影或边框应用于视图然后更改视图的框架 border/shadow 将不会自行更新自动地。您必须在 layoutSubviews 中调整图层大小,因此将您的代码更改为

class GradientView : UIView {
    private var gradient: CAGradientLayer?

    override func layoutSubviews() {
        super.layoutSubviews()
        self.gradient?.frame = self.bounds
    }

    required init?(coder: NSCoder) {
        super.init(coder:coder)
        self.customInit()
    }
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.customInit()
    }

    func animate(){
        UIView.animate(withDuration: 0.25, delay: 2, options: .curveLinear, animations: {
            self.frame.size.height = 80.0
            self.layoutIfNeeded()
        }, completion: nil)
    }

    func customInit(){
        let containerView = UIView()
        self.addSubview(containerView)
        containerView.frame = self.bounds
        self.autoresizingMask = [.flexibleHeight, .flexibleWidth]
        self.gradient = CAGradientLayer()
        gradient?.frame = self.bounds
        gradient?.name  = "grad1"
        gradient?.colors = [UIColor(red: 0, green: 91/255, blue: 200/255, alpha: 1), UIColor(red: 0, green: 131/255, blue: 232/255, alpha: 1)].map { [=10=].cgColor }
        gradient?.startPoint = CGPoint(x: 0.0,y: 0.0)
        gradient?.endPoint = CGPoint(x: 0.0,y: 1.0)
        if let gradient = self.gradient {
            containerView.layer.insertSublayer(gradient, at: 0)
        }
    }
}

希望对您有所帮助