Add animation after removeAllAnimations doesn't work

981 views Asked by At

I have simple application that is the red view transform position form left screen to right screen. I want when I hit remove button, the animation will be restart (the red view transform position form left screen to right screen again) but it doesn't works. The red view back to origin frame but it's not moving, but animationDidStop still called after duration.

class TestViewController: UIViewController, CAAnimationDelegate {

let testView : UIView = {
    let view = UIView()
    view.translatesAutoresizingMaskIntoConstraints = false
    view.backgroundColor = .red
    view.layer.borderColor = UIColor.black.cgColor
    view.layer.cornerRadius = 5
    return view
}()

let removeAniButton : UIButton = {
    let btn = UIButton(type: .system)
    btn.translatesAutoresizingMaskIntoConstraints = false
    btn.setTitle("Remove", for: .normal)
    return btn
}()

let addAniButton : UIButton = {
    let btn = UIButton(type: .system)
    btn.translatesAutoresizingMaskIntoConstraints = false
    btn.setTitle("Add", for: .normal)
    return btn
}()

override func viewDidLoad() {
    super.viewDidLoad()

    view.backgroundColor = .white

    view.addSubview(testView)
    testView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
    testView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
    testView.heightAnchor.constraint(equalToConstant: 100).isActive = true
    testView.widthAnchor.constraint(equalToConstant: 100).isActive = true

    view.addSubview(removeAniButton)
    removeAniButton.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 50).isActive = true
    removeAniButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
    removeAniButton.widthAnchor.constraint(equalToConstant: 100).isActive = true
    removeAniButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
    removeAniButton.addTarget(self, action: #selector(removeAnimation), for: .touchUpInside)

    view.addSubview(addAniButton)
    addAniButton.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 150).isActive = true
    addAniButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
    addAniButton.widthAnchor.constraint(equalToConstant: 100).isActive = true
    addAniButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
    addAniButton.addTarget(self, action: #selector(addAnimation), for: .touchUpInside)

    addAnimation()
    // Do any additional setup after loading the view.
}

func createAnimation() -> CAAnimation {
    let animation = CABasicAnimation(keyPath: "position.x")
    animation.fromValue = 0
    animation.toValue = self.view.frame.width
    animation.duration = 4
    animation.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionLinear) 
    animation.fillMode = kCAFillModeForwards
    animation.isRemovedOnCompletion = false
    animation.delegate = self
    return animation
}

func removeAnimation(){
    testView.layer.removeAllAnimations()
    testView.transform = .identity
    addAnimation()
}

func addAnimation(){
    testView.layer.add(createAnimation(), forKey: nil)
}

func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
    if flag {
        print("Animation is finished")
    }
  }
}

can anyone explain ?

1

There are 1 answers

1
Reinier Melian On

Your problem is that you are using the wrong keyPath for your animation, If you want to reset your animation using testView.transform = .identity you need use transform.translation.x instead of "position.x" as animation keyPath, also is not needed call removeAllAnimations() only calling again your addAnimation will do the job

use this code for animation creation

func createAnimation() -> CAAnimation {
    let animation = CABasicAnimation(keyPath: "transform.translation.x")
    animation.fromValue = 0
    animation.toValue = self.view.frame.width
    animation.duration = 4
    animation.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionLinear)
    animation.fillMode = kCAFillModeForwards
    animation.isRemovedOnCompletion = false
    return animation
}

func removeAnimation(){
    //customView.layer.removeAllAnimations()
    //customView.transform = .identity
    addAnimation()
}