ios - 动画移回原始位置后未调用UIView动画

标签 ios swift core-animation uiviewanimation cabasicanimation

目前,我正在使用一个按钮来激活一个UIView动画,在它的完成块中,我正在使用一个CABasicAnimation来返回它的起始位置。动画最初运行平稳,并返回到其原始起点,但当我再次按下按钮时,动画会自动从原始UIView动画结束的位置开始,而它应该从原始起点开始。

class ObjectCreateMoveViewController: UIViewController, CAAnimationDelegate {

  let square = UIView()

  override func viewDidLoad() {
    super.viewDidLoad()

    createSquare()

  }

  func createSquare() {

    square.frame =  CGRect(x: 10, y: 10, width: 100, height: 100)
    square.backgroundColor = UIColor.red
    square.layer.borderColor = UIColor.blue.cgColor
    square.layer.borderWidth = 4
    square.layer.cornerRadius = 2
    view.addSubview(square)
  }


  func transformAnimation () {

    let transAnimation = CABasicAnimation(keyPath: "transform.translation")
    transAnimation.toValue = NSValue(cgPoint: CGPoint(x: 10, y: 10))

    let rotAnimation = CABasicAnimation(keyPath: "transform.rotation")
    rotAnimation.toValue = -CGFloat.pi

    let scaleAnimation = CABasicAnimation(keyPath: "transform.scale.xy")
    scaleAnimation.toValue = NSNumber(value: 1)

    let groupTransform = CAAnimationGroup()
    groupTransform.duration = 3
    groupTransform.delegate = self
    groupTransform.beginTime = CACurrentMediaTime()
    groupTransform.animations = [transAnimation, rotAnimation, scaleAnimation]
    groupTransform.isRemovedOnCompletion = false
    groupTransform.fillMode = kCAFillModeForwards
    groupTransform.setValue("circle", forKey: "transform")
    square.layer.add(groupTransform, forKey: "transform")
  }

  func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
    if flag {
      //should be (10,10)but when I printed out the ending positions it was (60,60)
      square.layer.position.x = 60
      square.layer.position.y = 60
      print("This is the x point \(square.layer.position.x)")
      print("This is the y point \(square.layer.position.y)")
    }
  }

  @IBAction func transformButtonPressed(_ sender: Any) {

    UIView.animate(withDuration: 3, delay: 0, options: .curveEaseInOut, animations: {

      let translateTransform = CGAffineTransform(translationX: 150, y: 200)
      self.square.transform = translateTransform.scaledBy(x: 1.5, y: 1.5).rotated(by: CGFloat.pi/2)

    }, completion: { _ in

      self.transformAnimation()

    })
  }
}

最佳答案

这里有一些事情,所以让我先给你一些背景知识,然后再看看发生了什么,看看哪里出了问题。
扰流器:它是isRemovedOnCompletion = false和向前fillMode的组合。
一些背景
在iOS上,每个视图都有自己拥有和管理的层。设置视图的frametransform等属性会自动设置层的frametransform。对于层,设置的该值有时称为“模型值”,以将其与“表示值”区分开来,表示值是在进行中的动画期间层在屏幕上的显示方式。实际上,这意味着两件事:
如果在使用UIView动画设置视图动画时试图检查层位置的值,则position值将是动画块中指定的结束值。要获得屏幕上显示的“当前”值,必须查看层的表示层的值。
如果向层添加显式动画,则该层将在屏幕上设置更改的动画,但如果在动画期间检查动画属性,则该属性将保持不变。动画完成并移除后,层将再次渲染其模型值,使其看起来好像跳回了旧值,除非该值也已更改。
在这个案子里发生了什么
出发
视图(及其层)以(10, 10)的帧原点和(100, 100)的大小开始,使其成为center(层的position(60, 60)。由于未设置转换,因此使用“标识转换”(无转换)。
触发动画
当按下按钮时,将执行动画块,该动画块将视图(以及其层)的变换更改为平移(150, 200)缩放(1.5, 1.5)旋转π/2的变换。这将更改层的transform“model”值。
运行完成块
第一个动画完成后,将触发第二个动画。此时,模型值仍然是动画块中设置的值。
将三个变换动画配置为动画到(10, 10)的平移、的旋转和1的缩放。这些动画的组配置为在完成时不删除。此时不更新模型值。
动画组完成
动画组完成,但不会删除。此时,模型值仍然是在原始动画块中设置的变换。不删除CAAnimation会保留模型(属性是什么)和表示(它在屏幕上的显示方式)之间的差异。
注意,此时position应该是(60, 60),因为它从未更改过。更改transform属性不会更改position属性,只会更改显示在屏幕上的层。
第一个动画再次触发
下一次按下按钮时,将再次触发第一个动画。它将从“旧”值动画到“新”值。因为(模型的)属性从未改变,所以它们是相同的。
我不记得它是否有文档记录,但UIView动画在向层添加动画时(发生在幕后)使用已更改的属性作为键。
因为第二个动画已添加到关键帧transform的层,并且该层每个唯一关键帧只能有一个动画。将删除组动画。这使得视图看起来像是跳回第一个动画的“结束值”。
据我所知,UIKit正在做什么,然后视图将执行从一个值到同一个值的3秒动画(即不更改任何内容)。
UIView动画完成后,完成块再次运行第二个动画,将组动画添加到层中。
如何修复
真正的问题是这两行:

groupTransform.isRemovedOnCompletion = false
groupTransform.fillMode = kCAFillModeForwards

它们一起看起来好像做了正确的事情,因为它在屏幕上看起来是正确的,但是正如您在上面看到的,它们在动画完成后很长时间内保持了模型和表示层之间的临时差异。
一个好的经验法则是:完成时不移除动画的“唯一”时间是,如果动画正在设置视图/层的消失,并且视图/层在完成时被移除。
一种解决方法是删除这两行,然后在将动画组添加到层之前,还必须将视图(或层)的变换更新为新的"transform"值。
但是,在这种情况下,可以使用来自完成块内的另一个UIView动画来实现相同的动画。或者,可以使用UIView关键帧动画,该动画包含两个3秒的步骤。
尽可能地坚持使用UIView动画有一个好处,那就是模型值会被更新。

关于ios - 动画移回原始位置后未调用UIView动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44727262/

相关文章:

ios - 自定义 MKOverlayRenderer drawMapRect 函数不绘制多边形

ios - stringByAddingPercentEncodingWithAllowedCharacters 在空格上的行为很奇怪

iphone - 在特定方向移动 CAEmitterCell 动画

swift - 带有自定义形状框架的 UIView : Animation not behaving as expected

Swift动画查询

ios - 文件循环 : read file into NSString, 那就是 id 是文件名(没有.txt)

ios - 如何进行LinkingObject的迁移?

ios - Xcode 9 - 无法发出预编译 header

ios - 在 UIView 中的贝塞尔曲线路径内绘制/绘制草图颜色

ios - 每次我在 Git 中更改分支时,Xcode 4 构建方案都会搞砸