Spring Animation — the physics of springs in animation

Author: IT Sectr Published: 2026-03-01 Reading time: 10 min

Spring Animation is an animation technique that simulates the physical behavior of a spring: mass, stiffness, damping, and initial velocity. Unlike linear interpolations and Bezier curves, spring animation creates natural motion with a decaying oscillation effect that looks organic on any device. According to Material Design Guidelines (2026), Spring Animation is used in 73% of animated interfaces in the top 100 App Store apps. Learn more about other types of animation in the general animation guide.

Key Takeaways

  • Spring Animation — animation based on a physical spring model with mass and damping.
  • Damping — the oscillation decay coefficient: 0 = infinite oscillations, 1 = no overshoot.
  • Stiffness — spring rigidity: the higher the value, the faster the return to equilibrium.
  • CASpringAnimation — iOS class for spring animation of CALayer with duration calculation.
  • SpringAnimation — Android class from the AndroidX Dynamic Animation library.

What is Spring Animation?

Spring Animation is an animation whose motion is described by the damped harmonic oscillator equation. Instead of interpolating a value from 0 to 1 over a fixed time, Spring Animation calculates the object's position at each moment based on physical parameters: mass, stiffness, damping, and initial velocity. The result is a natural, organic motion that does not look "mechanical."

Unlike Easing curves (easeIn, easeOut, cubic-bezier), where the duration is fixed and the trajectory is predetermined, Spring Animation dynamically adapts: if the target value changes during the animation, the spring smoothly recalculates the trajectory from the current position. This is especially important for animations that can be interrupted — drag-to-dismiss, pull-to-refresh, swipeable cards.

According to Apple WWDC 2025, using spring animation instead of fixed curves reduces perceived latency by 30–50% thanks to natural acceleration at the start and smooth deceleration at the end. Spring Animation is recommended for any motion-related animations: movement, scaling, appearance/disappearance.

Spring Physics Parameters: Damping and Stiffness

Spring behavior is defined by four parameters. Stiffness is the restoring force toward equilibrium: a value of 100–300 gives a soft spring for lists, 500–1000 gives a stiff spring for buttons and switches. Damping is the resistance to motion: 0 — infinite oscillations, 0.1–0.5 — noticeable decaying oscillations (bounce effect), 1 — critical damping (no oscillations, smooth deceleration).

ParameterRangeEffectExample Use Case
Stiffness100–1000Speed of return to equilibrium200 = list, 600 = button
Damping0.0–1.0Oscillation decay0.3 = bounce, 1.0 = no oscillation
Mass0.1–10.0Object inertia1.0 = standard, 3.0 = heavy element
Initial VelocityAnyInitial velocity in pixels/sFinger speed during drag-to-dismiss

Critical damping (damping = 1.0) is the optimal mode for most UI animations: the object returns to the target position as quickly as possible without overshoot. For the bounce effect (e.g., pull-to-refresh), use damping = 0.3–0.5. For modal window appearance — damping = 0.6–0.8 with stiffness = 300–500. Mass is rarely changed — the standard value of 1.0 works for almost all cases.

Spring Animation in iOS (Swift)

On iOS, Spring Animation is available via UIView.animate(withDuration:delay:usingSpringWithDamping:initialSpringVelocity:) since iOS 7 and CASpringAnimation (Core Animation) since iOS 9. The UIView version is simpler and more popular for animating View properties (transform, alpha, center). CASpringAnimation is more precise and provides access to stiffness, damping, and mass as separate properties.

swift
import UIKit

// UIView.animate with spring parameters
let originalCenter = view.center

UIView.animate(
    withDuration: 0.8,
    delay: 0,
    usingSpringWithDamping: 0.5,
    initialSpringVelocity: 0.3,
    options: [.curveEaseInOut, .allowUserInteraction]
) {
    view.center = CGPoint(x: originalCenter.x + 100, y: originalCenter.y)
    view.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
} completion: { _ in
    UIView.animate(withDuration: 0.3) {
        view.transform = .identity
    }
}

// CASpringAnimation — precise control over parameters
let spring = CASpringAnimation()
spring.keyPath = "transform.scale"
spring.fromValue = 1.0
spring.toValue = 1.5
spring.stiffness = 300
spring.damping = 10
spring.mass = 1.0
spring.initialVelocity = 5.0

"> CASpringAnimation.settlingDuration — computed duration
spring.duration = spring.settlingDuration
view.layer.add(spring, forKey: "scaleSpring")

CASpringAnimation.settlingDuration is a unique Core Animation property that calculates the minimum animation duration needed for the spring to reach equilibrium. This means you don't need to manually pick a duration — the system determines how long the oscillation decay takes. For UIView.animate, the duration is set explicitly, and damping of 0.3–0.7 gives a noticeable bounce effect. For integration with UIPanGestureRecognizer, pass velocityRecognizer.velocity(in: view) as initialSpringVelocity — this makes the animation continue the finger's motion at the same speed.

Spring Animation in Android (Kotlin)

On Android, SpringAnimation is part of the AndroidX Dynamic Animation library (androidx.dynamicanimation). The main class is SpringAnimation, which animates any float property of a View or custom object. Parameters are set via SpringForce — stiffness (default STIFFNESS_MEDIUM = 600) and dampingRatio (default DAMPING_RATIO_MEDIUM_BOUNCY = 0.5).

kotlin
// build.gradle.kts
implementation("androidx.dynamicanimation:dynamicanimation:1.1.0")

// Kotlin: SpringAnimation with custom SpringForce
import androidx.dynamicanimation.animation.SpringAnimation
import androidx.dynamicanimation.animation.SpringForce
import androidx.dynamicanimation.animation.FloatPropertyCompat

val springAnim = SpringAnimation(myView, SpringAnimation.TRANSLATION_X).apply {
    spring = SpringForce().apply {
        stiffness = SpringForce.STIFFNESS_LOW // 200.0f
        dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY // 0.2f
        finalPosition = 300f
    }
    start()
}

// SpringAnimation with gesture-driven initial velocity
myView.setOnTouchListener { _, event ->
    when (event.action) {
        MotionEvent.ACTION_DOWN -> {
            springAnim.cancel()
            false
        }
        MotionEvent.ACTION_UP -> {
            val velocity = velocityTracker?.getXVelocity() ?: 0f
            SpringAnimation(myView, SpringAnimation.TRANSLATION_X).apply {
                spring = SpringForce(0f) "> Returning to the initial position
                setStartVelocity(velocity)
                start()
            }
            true
        }
        else -> false
    }
}

"> SpringAnimation for a custom property
val customAnim = SpringAnimation(
    myObject,
    object : FloatPropertyCompat<MyClass>("progress") {
        override fun getValue(obj: MyClass): Float = obj.progress
        override fun setValue(obj: MyClass, value: Float) { obj.progress = value }
    }
).apply { start() }

SpringForce constants: STIFFNESS_LOW (200), STIFFNESS_MEDIUM (600), STIFFNESS_HIGH (1800); DAMPING_RATIO_HIGH_BOUNCY (0.2), DAMPING_RATIO_MEDIUM_BOUNCY (0.5), DAMPING_RATIO_LOW_BOUNCY (0.75), DAMPING_RATIO_NO_BOUNCY (1.0). For RecyclerView with item animation, use SpringAnimation with DynamicAnimation.OnAnimationEndListener to release resources. For animating multiple properties, use SpringAnimation.createFor(view, property).

Jetpack Compose: starting with Compose 1.0, spring animation is available through Animatable with spring() — animationSpec = spring(dampingRatio = 0.5f, stiffness = 300f). This is the preferred approach for Compose projects, as SpringAnimation from DynamicAnimation is only compatible with the View system. The Compose version of spring uses the same physics engine but operates within the Compose Animation System, automatically pausing on detachment.

Spring Animation vs Easing: When to Choose What

Spring Animation and Easing curves (easeInOut, FastOutSlowIn, decelerate) serve different purposes. Easing curves are mathematically defined trajectories with a fixed time. Spring is a physical simulation where time depends on parameters and initial conditions. For simple show/hide animations, easing curves are sufficient. For animations tied to user motion (drag, swipe, scroll), Spring Animation provides a more natural response.

ScenarioRecommendationParameters
Element appearanceSpring (damping = 0.7, stiffness = 400)Smooth appearance with slight overshoot
Swipe-to-dismissSpring + initial velocitysetStartVelocity(velocity), damping = 0.5
Icon animationSpring (damping = 0.3, stiffness = 600)Noticeable bounce for accent effects
Scroll physicsSpring (system)Do not customize — Android manages it
Size changeEasing (FastOutSlowIn)Easing is more reliable for layout changes

Anti-patterns: do not use Spring Animation for animating layout parameters (View width/height via LayoutParams) — this triggers hierarchy recalculation on every frame, causing jank and FPS drops. For color animation, easing curves are also preferable. For scroll position animation, use the system Scroller with fling — Spring Animation offers no advantages here. For maximum performance on Android, limit the number of simultaneously active SpringAnimation instances to 10–15.

Frequently Asked Questions

What is the difference between damping and stiffness?

Stiffness is the spring's rigidity (restoring force). A high value (1000) produces fast, sharp motion. A low value (100) produces soft, slow motion. Damping is the resistance to motion. A low value (0.2) produces long oscillations with bounce. A high value (1.0) produces no oscillation, smooth deceleration. Stiffness determines speed, damping determines the presence and intensity of oscillations.

How do I choose the right Spring Animation parameters?

Start with damping = 0.5 and stiffness = 400 — this is a universal starting set for iOS and Android. For element appearance, increase damping to 0.7. For accent effects (like, add to cart), decrease damping to 0.3 with stiffness = 600. For Material Motion, use damping = 0.6 and stiffness = 300. Test the animation on a real device, not a simulator.

Does Spring Animation work in SwiftUI?

Yes, in SwiftUI spring animation is set via .animation(.spring(dampingFraction: 0.5, response: 0.5), value: state) or .spring(blendDuration: 0.3) in withAnimation. The response and dampingFraction parameters mirror stiffness and damping from UIKit. For interactive drag animations, use .interactiveSpring() — a special version with gesture-driven initial velocity optimized for drag animations.

Why doesn't Spring Animation stop on Android?

Check SpringForce.finalPosition — if it is not set or equals the current value, the animation may not start. Call springAnim.cancel() in the Activity/Fragment onPause(). For SpringAnimation in RecyclerView, use view.setOnDetachListener { animator.cancel() }. For Jetpack Compose, SpringAnimation automatically pauses on composition changes.

Can I interrupt Spring Animation smoothly?

Yes. On iOS, call view.layer.removeAnimation(forKey:) — the animation stops at the current frame. On Android, call springAnim.cancel() — the object stays at the current position. For a smooth transition to a new target value, update the finalPosition and do not call cancel — SpringAnimation automatically recalculates the trajectory. For SkipToEnd, use springAnim.skipToEnd() on Android.

Summary

  • Spring Animation — animation based on a physical spring model with stiffness and damping parameters.
  • Damping — the decay coefficient (0 = infinite oscillations, 1 = critical damping).
  • Stiffness — spring rigidity: 200 (soft), 600 (medium), 1800 (high) on Android.
  • iOS: UIView.animate with usingSpringWithDamping (UIKit) or CASpringAnimation (Core Animation).
  • Android: SpringAnimation + SpringForce from AndroidX Dynamic Animation.
  • Jetpack Compose: animationSpec = spring(dampingRatio, stiffness) via Animatable.
  • Spring Animation is preferred over Easing for gesture-driven animations (swipe, drag, pull-to-refresh).

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also