Spring physics animations implementation in iOS app

NOVASOLUTIONS.TECHNOLOGY is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
Spring physics animations implementation in iOS app
Medium
from 1 business day to 3 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

Implementing Spring Animations (Physics-Based) in iOS Applications

Spring animations make interfaces feel alive—elements don't just move, they "bounce," slightly overshooting their target and returning. iOS uses them everywhere: icons on long press, cards in App Store, keyboard keys. The difference between "system-made" and "almost system-made" lies in correct physical model parameters.

UIKit: UISpringTimingParameters and UIViewPropertyAnimator

Before iOS 10, spring animations used UIView.animate(withDuration:delay:usingSpringWithDamping:initialSpringVelocity:). The dampingRatio (0–1) and initialVelocity parameters work, but it's a simplified model—not true spring physics.

From iOS 10 onwards, use UISpringTimingParameters with mass, stiffness, and damping:

let timingParams = UISpringTimingParameters(
    mass: 1.0,
    stiffness: 170,
    damping: 26,
    initialVelocity: CGVector(dx: 0, dy: 0)
)
let animator = UIViewPropertyAnimator(duration: 0, timingParameters: timingParams)
animator.addAnimations {
    self.cardView.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
}
animator.startAnimation()

duration: 0—with spring timing, duration is ignored; the animation lasts as long as the spring needs to settle. This is correct—don't set duration for springs.

Parameter presets for typical cases: stiffness: 300, damping: 30 is a quick, elastic animation (tap feedback). stiffness: 120, damping: 14 is a slow, soft spring (bottom sheet appearance). stiffness: 400, damping: 40 is stiff without overshoot (toggle).

UIViewPropertyAnimator supports isInterruptible = true—stop and redirect the animation mid-flight. Critical for gesture-driven UI: if a user starts dragging a card down then changes mind, the animation smoothly reverses from current velocity.

SwiftUI: spring() and .interpolatingSpring()

SwiftUI offers several options:

// Simple spring with dampingFraction
withAnimation(.spring(response: 0.4, dampingFraction: 0.7)) {
    isExpanded.toggle()
}

// Physical model via interpolatingSpring
withAnimation(.interpolatingSpring(stiffness: 170, damping: 26)) {
    offset = targetOffset
}

// iOS 17+: new Spring type
withAnimation(.spring(.bouncy(duration: 0.4, extraBounce: 0.1))) {
    scale = 1.0
}

.spring(response:dampingFraction:) is simpler: response is approximate duration (not strict), dampingFraction 1.0 is critical damping with no overshoot, below 1.0 is overshoot. For most UI: response: 0.3–0.5, dampingFraction: 0.7–0.85.

iOS 17 brought named spring presets: .bouncy, .smooth, .snappy—useful for quick prototyping, but for final product, specify parameters explicitly.

Velocity matching on interruption: when gesture interrupts animation, the new spring should start from current velocity. In SwiftUI, use @GestureState and withAnimation with correct initialVelocity. In UIKit, use UIViewPropertyAnimator.fractionComplete and continueAnimation(withTimingParameters:durationFactor:).

Gesture-Driven Spring: UIPanGestureRecognizer + Spring

The liveliest case is a card you can drag and it springs back or flies to the next position:

@objc func handlePan(_ gesture: UIPanGestureRecognizer) {
    let translation = gesture.translation(in: view)

    switch gesture.state {
    case .changed:
        cardView.transform = CGAffineTransform(translationX: 0, y: translation.y)
    case .ended:
        let velocity = gesture.velocity(in: view)
        let velocityVector = CGVector(dx: 0, dy: velocity.y / 1000) // normalization

        let timingParams = UISpringTimingParameters(
            mass: 1, stiffness: 200, damping: 28,
            initialVelocity: velocityVector
        )
        let animator = UIViewPropertyAnimator(duration: 0, timingParameters: timingParams)
        animator.addAnimations {
            self.cardView.transform = .identity
        }
        animator.startAnimation()
    default: break
    }
}

Take initialVelocity from gesture velocity, normalize by dividing by ~1000 (UISpringTimingParameters scale differs from points/second gesture velocity).

Timeline

Adding spring animations to existing UI components (2–4 elements) takes 1–2 days with device testing. Gesture-driven interactive screen with spring physics takes 2–3 days. Cost is calculated individually.