【问题标题】:Why is UIView animation not working when starting right after view is added?为什么在添加视图后立即启动 UIView 动画不起作用?
【发布时间】:2017-07-01 22:45:39
【问题描述】:

UIView 的动画应该在视图添加到父视图后立即开始:

class myView: UIView {
    override func didMoveToSuperview() {
        super.didMoveToSuperview()

        UIView.animate(
            withDuration: duration,
            delay: 0,
            options: .curveLinear,
            animations: {
                CATransaction.begin()
                CATransaction.setAnimationDuration(duration)
                self.layer.colors = [color1, color2]
                CATransaction.commit()
        },
            completion: nil
        )
    }
}

但是,结果是当视图在父视图中可见时动画已经结束。 UIView.animate 没有动画,而是立即设置self.layer.colors,可能是因为调用didMoveToSuperview 时视图还不可见。

如何让动画正常启动?

【问题讨论】:

  • 在视图控制器的生命周期中,您的 MyView 实例添加到视图层次结构中的哪个位置?
  • @thefredelement 覆盖两个绘图函数都没有帮助,结果相同。
  • @beyowulf 在super.viewDidAppear(animated) 之后。
  • 您是否要为CAGradientLayer 制作动画?
  • @beyowulf 是的..

标签: ios swift uiview uiviewanimation catransaction


【解决方案1】:

可以通过创建CABasicAnimation 并将其添加到您的CAGradientLayer 来使用核心动画制作渐变动画。您不需要将其包装在 UIView 动画块中,并且可以从 viewDidMoveToSuperview 执行此操作,前提是您在将根视图添加到 @987654326 之后的某个时间将 UIView 子类实例添加到视图层次结构中@。例如,在操场上可以写:

import UIKit
import PlaygroundSupport

class MyView: UIView
{
    var duration = 20.0

    var fromColors = [UIColor.orange.cgColor, UIColor.blue.cgColor]
    var toColors = [UIColor.red.cgColor, UIColor.green.cgColor]

    override func didMoveToSuperview() {
        super.didMoveToSuperview()

        let gradientLayer = CAGradientLayer()
        gradientLayer.frame = bounds
        layer.addSublayer(gradientLayer)

        let animation = CABasicAnimation(keyPath: "colors")
        animation.fromValue = fromColors
        animation.toValue = toColors
        animation.duration = duration
        gradientLayer.add(animation, forKey: nil)

        gradientLayer.colors = toColors
    }
}

class ViewController: UIViewController
{
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        let myView = MyView(frame: view.bounds)
        view.addSubview(myView)
    }
}

PlaygroundPage.current.liveView = ViewController()

并看到一个 20 秒的动画,从垂直的橙色到蓝色渐变动画到垂直的红色到绿色渐变。

【讨论】:

  • 谢谢,现在可以正常使用了。唯一需要改变的是在添加动画gradientLayer.add(animation, forKey: nil)之前应该设置最终状态gradientLayer.colors = toColors。否则在做连续动画时有时会闪烁。甚至不再需要在didMoveToSuperview 中启动动画,它也可以在init 函数中使用。
猜你喜欢
  • 1970-01-01
  • 2012-01-31
  • 1970-01-01
  • 2021-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多