【问题标题】:Animation not working on inserted CAGradientLayer as sublayer动画不适用于插入的 CAGradientLayer 作为子层
【发布时间】:2020-09-12 21:40:49
【问题描述】:

我想在加载 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 { $0.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层没有任何作用。

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

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 { $0.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)
    }
}

但这并没有帮助。

我该如何解决这个问题?

提前致谢。

【问题讨论】:

  • 您尝试过我发布的解决方案吗?成功了吗?

标签: ios swift animation cagradientlayer


【解决方案1】:

这意味着新添加的子图层不会调整大小 布局IfNeeded()

当父 View 的 bound/frame 发生变化时,Layers 不会自行调整大小,例如:如果你对 view 应用阴影或边框,然后更改 view 的边框,边框/阴影不会自动更新自己。您必须调整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 { $0.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)
        }
    }
}

希望对你有帮助

【讨论】:

  • 感谢您的回复!这适用于以编程方式添加视图。但我观察到 animate() 函数中提到的延迟没有任何影响。知道为什么会这样吗?
  • 如果有帮助,请考虑接受答案。为什么延迟不起作用不在当前问题的范围内,但我会检查并更新答案
猜你喜欢
  • 1970-01-01
  • 2021-08-29
  • 2021-05-22
  • 2015-01-06
  • 1970-01-01
  • 2017-01-20
  • 2012-02-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多