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 ?
Your problem is that you are using the wrong keyPath for your animation, If you want to reset your animation using
testView.transform = .identityyou need usetransform.translation.xinstead of "position.x" as animation keyPath, also is not needed callremoveAllAnimations()only calling again youraddAnimationwill do the jobuse this code for animation creation