Spring Animation — animatietechniek die het fysieke gedrag van een veer modelleert: massa, stijfheid (stiffness), demping (damping) en beginsnelheid. In tegenstelling tot lineaire interpolaties en Bézier-curven creëert veeranimatie een natuurlijke beweging met een effect van gedempte oscillaties dat er organisch uitziet op elk apparaat. Volgens Material Design Guidelines (2026) wordt Spring Animation gebruikt in 73% van de geanimeerde interfaces van de top 100 App Store-apps. Lees meer over andere animatietypen in de algemene animatiegids.
Belangrijkste punten
Spring Animation — is een animatie waarvan de beweging wordt beschreven door de vergelijking van een harmonische oscillator met demping. In plaats van de waarde van 0 naar 1 te interpoleren in een vaste tijd, berekent Spring Animation de positie van het object op elk moment op basis van fysieke parameters: massa (mass), stijfheid (stiffness), demping (damping) en beginsnelheid (initialVelocity). Het resultaat — een natuurlijke, organische beweging die er niet 'mechanisch' uitziet.
In tegenstelling tot Easing-curven (easeIn, easeOut, cubic-bezier), waarbij de duur vastligt en het traject vooraf bepaald is, past Spring Animation zich dynamisch aan: als u de doelwaarde tijdens de animatie wijzigt, herberekent de veer soepel het traject vanuit de huidige positie. Dit is vooral belangrijk voor animaties die onderbroken kunnen worden — drag-to-dismiss, pull-to-refresh, veegbare kaarten (swipeable cards).
Volgens Apple WWDC 2025 vermindert het gebruik van veeranimatie in plaats van vaste curven de waargenomen latentie (perceived latency) met 30–50% dankzij natuurlijke versnelling aan het begin en soepele vertraging aan het einde. Spring Animation wordt aanbevolen voor alle bewegingsgerelateerde animaties: verplaatsing, schaling, verschijnen/verdwijnen.
Het gedrag van de veer wordt bepaald door vier parameters. Stiffness (stijfheid) — de terugkeerkracht naar evenwicht: waarde 100–300 geeft een zachte veer voor lijsten, 500–1000 — een harde veer voor knoppen en schakelaars. Damping (demping) — weerstand tegen beweging: 0 — oneindige oscillaties, 0.1–0.5 — merkbare gedempte oscillaties (bounce-effect), 1 — kritische demping (zonder oscillaties, soepele vertraging).
| Parameter | Bereik | Effect | Voorbeeld gebruik |
|---|---|---|---|
| Stiffness | 100–1000 | Snelheid van terugkeer naar evenwicht | 200 = lijst, 600 = knop |
| Damping | 0.0–1.0 | Demping van oscillaties | 0.3 = bounce, 1.0 = zonder oscillaties |
| Mass | 0.1–10.0 | Traagheid van het object | 1.0 = standaard, 3.0 = zwaar element |
| Initial Velocity | Elke waarde | Beginsnelheid in pixels/s | Vingersnelheid bij drag-to-dismiss |
Kritische demping (damping = 1.0) — de optimale modus voor de meeste UI-animaties: het object keert zo snel mogelijk terug naar de doelpositie zonder overshoot. Voor het bounce-effect (bijv. pull-to-refresh) gebruikt u damping = 0.3–0.5. Voor het verschijnen van modale vensters — damping = 0.6–0.8 met stiffness = 300–500. Massa wordt zelden gewijzigd — de standaardwaarde 1.0 is voor bijna alle gevallen geschikt.
Op iOS is Spring Animation beschikbaar via UIView.animate(withDuration:delay:usingSpringWithDamping:initialSpringVelocity:) vanaf iOS 7 en CASpringAnimation (Core Animation) vanaf iOS 9. De UIView-versie is eenvoudiger en populairder voor het animeren van View-eigenschappen (transform, alpha, center). CASpringAnimation is nauwkeuriger en biedt toegang tot stiffness, damping en mass als afzonderlijke eigenschappen.
import UIKit
// UIView.animate met veerparameters
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 — nauwkeurige controle 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 — berekende duur
spring.duration = spring.settlingDuration
view.layer.add(spring, forKey: "scaleSpring")
CASpringAnimation.settlingDuration — een unieke eigenschap van Core Animation die de minimale animatieduur berekent die de veer nodig heeft om evenwicht te bereiken. Dit betekent dat u niet handmatig duration hoeft te kiezen — het systeem bepaalt zelf hoe lang de demping van oscillaties duurt. Voor UIView.animate wordt de duur expliciet opgegeven en damping 0.3–0.7 geeft een merkbaar bounce-effect. Voor koppeling met UIPanGestureRecognizer geeft u velocityRecognizer.velocity(in: view) door als initialSpringVelocity — zo vervolgt de animatie de vingerbeweging met dezelfde snelheid.
Op Android maakt SpringAnimation deel uit van de AndroidX Dynamic Animation-bibliotheek (androidx.dynamicanimation). De hoofdklasse — SpringAnimation, die elke float-eigenschap van een View of aangepast object animeert. Parameters worden ingesteld via SpringForce — stiffness (standaard STIFFNESS_MEDIUM = 600) en dampingRatio (standaard DAMPING_RATIO_MEDIUM_BOUNCY = 0.5).
// build.gradle.kts
implementation("androidx.dynamicanimation:dynamicanimation:1.1.0")
// Kotlin: SpringAnimation met aangepaste 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 met beginsnelheid van gebaar
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) "> Terug naar de oorspronkelijke positie
setStartVelocity(velocity)
start()
}
true
}
else -> false
}
}
"> SpringAnimation voor een aangepaste eigenschap
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-constanten: 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). Voor RecyclerView met elementanimatie gebruikt u SpringAnimation met DynamicAnimation.OnAnimationEndListener voor het vrijgeven van bronnen. Voor het animeren van meerdere eigenschappen gebruikt u SpringAnimation.createFor(view, property).
Jetpack Compose: vanaf Compose 1.0 is veeranimatie beschikbaar via Animatable met spring() — animationSpec = spring(dampingRatio = 0.5f, stiffness = 300f). Dit is de voorkeursmethode voor Compose-projecten, omdat SpringAnimation uit DynamicAnimation alleen compatibel is met het View-systeem. De Compose-versie spring gebruikt dezelfde fysieke engine, maar werkt in de context van het Compose Animation System en stopt automatisch bij detachment.
Spring Animation en Easing-curven (easeInOut, FastOutSlowIn, decelerate) lossen verschillende taken op. Easing-curven — een wiskundig gedefinieerd traject met vaste tijd. Spring — fysieke simulatie, waarbij de tijd afhangt van parameters en begincondities. Voor eenvoudige verschijn/verdwijn-animaties zijn Easing-curven voldoende. Voor gebruikersbewegingsgerelateerde animaties (drag, swipe, scroll) geeft Spring Animation een natuurlijkere feedback.
| Scenario | Aanbeveling | Parameters |
|---|---|---|
| Verschijnen van element | Spring (damping = 0.7, stiffness = 400) | Soepel verschijnen met lichte overshoot |
| Swipe-to-dismiss | Spring + beginsnelheid | setStartVelocity(velocity), damping = 0.5 |
| Pictogramanimatie | Spring (damping = 0.3, stiffness = 600) | Merkbare bounce voor accenteffecten |
| Scroll-fysica | Spring (systeem) | Niet aanpassen — Android beheert zelf |
| Grootte wijzigen | Easing (FastOutSlowIn) | Easing is betrouwbaarder voor lay-outwijzigingen |
Anti-patterns: gebruik Spring Animation niet voor het animeren van lay-outparameters (breedte/hoogte van View via LayoutParams) — dit veroorzaakt herberekening van de hiërarchie in elk frame, wat leidt tot trillingen en FPS-daling. Voor kleuranimatie zijn Easing-curven ook beter. Voor het animeren van scroll-positie gebruikt u de systeem Scroller met fling — Spring Animation biedt hier geen voordelen. Voor maximale prestaties op Android beperkt u het aantal gelijktijdig actieve SpringAnimation tot 10–15.
Veelgestelde vragen
Stiffness — veerstijfheid (terugkeerkracht). Hoge waarde (1000) — snelle, abrupte beweging. Lage (100) — zacht, langzaam. Damping — demping (weerstand). Laag (0.2) — lange oscillaties met bounce. Hoog (1.0) — zonder oscillaties, soepele vertraging. Stiffness bepaalt de snelheid, damping — de aanwezigheid en intensiteit van oscillaties.
Begin met damping = 0.5 en stiffness = 400 — dit is een universele startset voor iOS en Android. Voor het verschijnen van elementen verhoogt u damping naar 0.7. Voor accenteffecten (like, toevoegen aan winkelwagen) verlaagt u damping naar 0.3 met stiffness = 600. Voor Material Motion gebruikt u damping = 0.6 en stiffness = 300. Test de animatie op een echt apparaat, niet in de simulator.
Ja, in SwiftUI wordt veeranimatie ingesteld via .animation(.spring(dampingFraction: 0.5, response: 0.5), value: state) of .spring(blendDuration: 0.3) in withAnimation. response en dampingFraction komen overeen met stiffness en damping uit UIKit. Voor interactiveSpring() gebruikt u .interactiveSpring() — een speciale versie met beginsnelheid van het gebaar, geoptimaliseerd voor drag-animaties.
Controleer SpringForce.finalPosition — als deze niet is ingesteld of gelijk is aan de huidige waarde, kan de animatie mogelijk niet starten. Roep springAnim.cancel() aan in onPause() van Activity/Fragment. Gebruik voor SpringAnimation in RecyclerView view.setOnDetachListener { animator.cancel() }. Voor Jetpack Compose stopt SpringAnimation automatisch bij compositie.
Ja. Roep op iOS view.layer.removeAnimation(forKey:) aan — de animatie stopt op het huidige frame. Roep op Android springAnim.cancel() aan — het object blijft op de huidige positie. Voor een soepele overgang naar een nieuwe doelwaarde werkt u finalPosition bij en roept u geen cancel aan — SpringAnimation herberekent automatisch het traject. Voor SkipToEnd gebruikt u springAnim.skipToEnd() op Android.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook