0
0
iOS Swiftmobile~20 mins

Custom animation timing in iOS Swift - Mini App: Build & Ship

Choose your learning style9 modes available
Build: Animated Circle Screen
This screen shows a circle that moves horizontally with a custom timing curve animation when you tap a button.
Target UI
-------------------------
|                       |
|                       |
|         (●)           |
|                       |
|                       |
|       [Animate]        |
-------------------------
Display a circle shape centered vertically near the left side of the screen.
Add a button labeled 'Animate' at the bottom center.
When the button is tapped, animate the circle moving horizontally to the right side.
Use a custom timing curve for the animation (not linear or ease-in/out).
The animation duration should be 2 seconds.
After animation completes, the circle should stay at the right side.
Starter Code
iOS Swift
import UIKit

class AnimatedCircleViewController: UIViewController {
    let circleView = UIView()
    let animateButton = UIButton(type: .system)

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        circleView.backgroundColor = .systemBlue
        circleView.frame = CGRect(x: 40, y: view.bounds.midY - 25, width: 50, height: 50)
        circleView.layer.cornerRadius = 25
        view.addSubview(circleView)

        animateButton.setTitle("Animate", for: .normal)
        animateButton.frame = CGRect(x: 0, y: view.bounds.height - 80, width: 120, height: 44)
        animateButton.center.x = view.center.x
        animateButton.addTarget(self, action: #selector(animateCircle), for: .touchUpInside)
        view.addSubview(animateButton)

        // TODO: Add any additional setup if needed
    }

    @objc func animateCircle() {
        // TODO: Implement animation with custom timing curve
    }
}
Task 1
Task 2
Task 3
Solution
iOS Swift
import UIKit

class AnimatedCircleViewController: UIViewController {
    let circleView = UIView()
    let animateButton = UIButton(type: .system)

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        circleView.backgroundColor = .systemBlue
        circleView.frame = CGRect(x: 40, y: view.bounds.midY - 25, width: 50, height: 50)
        circleView.layer.cornerRadius = 25
        view.addSubview(circleView)

        animateButton.setTitle("Animate", for: .normal)
        animateButton.frame = CGRect(x: 0, y: view.bounds.height - 80, width: 120, height: 44)
        animateButton.center.x = view.center.x
        animateButton.addTarget(self, action: #selector(animateCircle), for: .touchUpInside)
        view.addSubview(animateButton)
    }

    @objc func animateCircle() {
        let endX = view.bounds.width - 90 // 40 padding + 50 width
        let timingParameters = UICubicTimingParameters(controlPoint1: CGPoint(x: 0.68, y: -0.55), controlPoint2: CGPoint(x: 0.27, y: 1.55))
        let animator = UIViewPropertyAnimator(duration: 2.0, timingParameters: timingParameters)

        animator.addAnimations {
            self.circleView.frame.origin.x = endX
        }

        animator.startAnimation()
    }
}

We use UIViewPropertyAnimator to create an animation with a custom cubic Bezier timing curve. This curve is defined by two control points that shape the speed of the animation, making it non-linear and more dynamic than standard ease-in or ease-out.

The circle starts near the left side and moves horizontally to the right side over 2 seconds. The animateCircle() method triggers this animation when the button is tapped.

This approach gives you fine control over the animation timing, making the movement feel more natural or playful depending on the curve.

Final Result
Completed Screen
-------------------------
|                       |
|                       |
|                       |
|                       |
|                       |
|       (●)             |
|                       |
|                       |
|                       |
|       [Animate]        |
-------------------------
When the user taps the 'Animate' button, the blue circle smoothly moves from the left side to the right side of the screen over 2 seconds.
The movement speed changes according to the custom timing curve, making the animation feel dynamic.
After the animation finishes, the circle stays at the right side.
Stretch Goal
Add a 'Reset' button that moves the circle back to the left side with the same custom animation.
💡 Hint
Create another UIButton below the 'Animate' button and implement a similar UIViewPropertyAnimator animation that sets circleView.frame.origin.x back to the starting position.