aheze
aheze

Reputation: 30564

Remove delay when interrupting UIView animation with another animation

I'm interrupting an in-flight animation with another animation. It's working alright, but there's a significant delay before the animation changes.

When I click Reset to 1 after Animate to 5, the square on top continues expanding for another second before shrinking. For the square on the bottom, I forced the animation to stop with layer.removeAllAnimations() and it shrinks instantly... but, it starts from the full 5x scale value instead of the current value.

Image of the problem

Here's my code:

class ViewController: UIViewController {
    
    let resetButton = UIButton(type: .system)
    let finishButton = UIButton(type: .system)
    
    let squareView = UIView(frame: CGRect(x: 100, y: 100, width: 30, height: 30))
    let referenceSquareView = UIView(frame: CGRect(x: 100, y: 100, width: 30, height: 30))
    let squareView2 = UIView(frame: CGRect(x: 100, y: 300, width: 30, height: 30))
    let referenceSquareView2 = UIView(frame: CGRect(x: 100, y: 300, width: 30, height: 30))
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        resetButton.frame = CGRect(x: 200, y: 80, width: 160, height: 20)
        finishButton.frame = CGRect(x: 200, y: 140, width: 160, height: 20)
        
        view.addSubview(resetButton)
        view.addSubview(finishButton)
        
        view.addSubview(referenceSquareView)
        view.addSubview(squareView)
        view.addSubview(referenceSquareView2)
        view.addSubview(squareView2)
        referenceSquareView.transform = CGAffineTransform(scaleX: 5, y: 5)
        referenceSquareView2.transform = CGAffineTransform(scaleX: 5, y: 5)
        
        squareView.backgroundColor = UIColor.blue
        referenceSquareView.backgroundColor = UIColor.red
        squareView2.backgroundColor = UIColor.blue
        referenceSquareView2.backgroundColor = UIColor.red
        
        resetButton.setTitle("Reset to 1", for: .normal)
        resetButton.setTitleColor(.blue, for: .normal)
        resetButton.addTarget(self, action: #selector(resetTo1(_:)), for: .touchUpInside)
        finishButton.setTitle("Animate to 5", for: .normal)
        finishButton.setTitleColor(.blue, for: .normal)
        finishButton.addTarget(self, action: #selector(animateTo5(_:)), for: .touchUpInside)
    }
    @objc func resetTo1(_ sender: UIButton!) {
        UIView.animate(withDuration: 3) {
            self.squareView.transform = CGAffineTransform(scaleX: 1, y: 1)
        }
        
        self.squareView2.layer.removeAllAnimations() /// removing animations for the bottom square
        UIView.animate(withDuration: 3) {
            self.squareView2.transform = CGAffineTransform(scaleX: 1, y: 1)
        }
    }
    @objc func animateTo5(_ sender: UIButton!) {
        UIView.animate(withDuration: 3) {
            self.squareView.transform = CGAffineTransform(scaleX: 5, y: 5)
        }
        
        self.squareView2.layer.removeAllAnimations() /// removing animations for the bottom square
        UIView.animate(withDuration: 3) {
            self.squareView2.transform = CGAffineTransform(scaleX: 5, y: 5)
        }
    }
}

Is there any way I can change the animation instantly?

Upvotes: 0

Views: 109

Answers (1)

Hai Pham
Hai Pham

Reputation: 233

When you call self.squareView2.transform = CGAffineTransform(scaleX: 5, y: 5), squareView2 is immediately has transform value 5 without waiting for 3s(even though you change the duration to 3600s). The animation that the rectangle size increasing you are seeing in the app is just an animation layer. So, if you call removeAllAnimations,it will immediately show the squareView2 with transform value 5.

To work around this issue, I think you can use a timer instead. Set a flag scale with value 1. And then, when you tap "Animate to 5", for every 0.3s, increase scale for 0.5. So if you want to stop, just invalidate the timer and schedule another timer to decrease the scale value

Upvotes: 1

Related Questions