Spring Animation — technika animace modelující fyzikální chování pružiny: hmotnost, tuhost (stiffness), tlumení (damping) a počáteční rychlost. Na rozdíl od lineárních interpolací a Bézierových křivek vytváří pružinová animace přirozený pohyb s efektem tlumených kmitů, který vypadá organicky na všech zařízeních. Podle Material Design Guidelines (2026) se Spring Animation používá v 73% animovaných rozhraní top 100 aplikací App Store. Více o dalších typech animací si přečtěte v obecném průvodci animacemi.
Hlavní body
Spring Animation — je animace, jejíž pohyb je popsán rovnicí harmonického oscilátoru s tlumením. Namísto interpolace hodnoty z 0 na 1 v pevném čase Spring Animation vypočítává polohu objektu v každém okamžiku na základě fyzikálních parametrů: hmotnost (mass), tuhost (stiffness), tlumení (damping) a počáteční rychlost (initialVelocity). Výsledkem je přirozený, organický pohyb, který nevypadá „mechanicky”.
Na rozdíl od Easing křivek (easeIn, easeOut, cubic-bezier), kde je doba trvání pevná a trajektorie předem daná, se Spring Animation dynamicky přizpůsobuje: pokud během animace změníte cílovou hodnotu, pružina plynule přepočítá trajektorii z aktuální polohy. To je obzvláště důležité pro animace, které mohou být přerušeny — drag-to-dismiss, pull-to-refresh, posuvné karty (swipeable cards).
Podle Apple WWDC 2025 snižuje použití pružinové animace namísto pevných křivek vnímanou latenci (perceived latency) o 30–50% díky přirozenému zrychlení na začátku a plynulému zpomalení na konci. Spring Animation se doporučuje pro všechny animace související s pohybem: posun, škálování, zobrazení/skrytí.
Chování pružiny určují čtyři parametry. Stiffness (tuhost) — síla návratu do rovnováhy: hodnota 100–300 dává měkkou pružinu pro seznamy, 500–1000 — tvrdou pro tlačítka a přepínače. Damping (tlumení) — odpor proti pohybu: 0 — nekonečné kmity, 0.1–0.5 — znatelné tlumené kmity (efekt odrazu), 1 — kritické tlumení (bez kmitů, plynulé zpomalení).
| Parametr | Rozsah | Efekt | Příklad použití |
|---|---|---|---|
| Stiffness | 100–1000 | Rychlost návratu do rovnováhy | 200 = seznam, 600 = tlačítko |
| Damping | 0.0–1.0 | Tlumení kmitů | 0.3 = odraz, 1.0 = bez kmitů |
| Mass | 0.1–10.0 | Setrvačnost objektu | 1.0 = standard, 3.0 = těžký prvek |
| Initial Velocity | Libovolný | Počáteční rychlost v px/s | Rychlost prstu při drag-to-dismiss |
Kritické tlumení (damping = 1.0) — optimální režim pro většinu UI animací: objekt se vrací do cílové polohy maximálně rychle bez překmitu. Pro efekt odrazu (např. pull-to-refresh) použijte damping = 0.3–0.5. Pro zobrazení modálních oken — damping = 0.6–0.8 s stiffness = 300–500. Hmotnost se mění zřídka — standardní hodnota 1.0 vyhovuje téměř všem případům.
V iOS je Spring Animation k dispozici prostřednictvím UIView.animate(withDuration:delay:usingSpringWithDamping:initialSpringVelocity:) od iOS 7 a CASpringAnimation (Core Animation) od iOS 9. Verze UIView je jednodušší a oblíbenější pro animaci vlastností View (transform, alpha, center). CASpringAnimation je přesnější a poskytuje přístup k stiffness, damping a mass jako samostatným vlastnostem.
import UIKit
// UIView.animate s pružinovými parametry
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 — přesná kontrola parametrů
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 — vypočítaná doba trvání
spring.duration = spring.settlingDuration
view.layer.add(spring, forKey: "scaleSpring")
CASpringAnimation.settlingDuration — jedinečná vlastnost Core Animation, která vypočítává minimální dobu trvání animace potřebnou k dosažení rovnováhy pružiny. To znamená, že nemusíte ručně volit duration — systém sám určí, jak dlouho bude tlumení kmitů trvat. U UIView.animate se doba trvání zadává explicitně a damping 0.3–0.7 poskytuje znatelný efekt odrazu. Pro propojení s UIPanGestureRecognizer předejte velocityRecognizer.velocity(in: view) jako initialSpringVelocity — animace tak bude pokračovat v pohybu prstu stejnou rychlostí.
V Android je SpringAnimation součástí knihovny AndroidX Dynamic Animation (androidx.dynamicanimation). Hlavní třída — SpringAnimation, která animuje libovolnou float vlastnost View nebo vlastního objektu. Parametry se nastavují prostřednictvím SpringForce — stiffness (výchozí STIFFNESS_MEDIUM = 600) a dampingRatio (výchozí DAMPING_RATIO_MEDIUM_BOUNCY = 0.5).
// build.gradle.kts
implementation("androidx.dynamicanimation:dynamicanimation:1.1.0")
// Kotlin: SpringAnimation s vlastním 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 s počáteční rychlostí z gesta
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) "> Návrat do výchozí polohy
setStartVelocity(velocity)
start()
}
true
}
else -> false
}
}
"> SpringAnimation pro vlastní vlastnost
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() }
Konstanty SpringForce: 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). Pro RecyclerView s animací prvků použijte SpringAnimation s DynamicAnimation.OnAnimationEndListener pro uvolnění zdrojů. Pro animaci více vlastností použijte SpringAnimation.createFor(view, property).
Jetpack Compose: od Compose 1.0 je pružinová animace k dispozici prostřednictvím Animatable s spring() — animationSpec = spring(dampingRatio = 0.5f, stiffness = 300f). Toto je preferovaný způsob pro Compose projekty, protože SpringAnimation z DynamicAnimation je kompatibilní pouze se systémem View. Verze Compose spring používá stejný fyzikální engine, ale pracuje v kontextu Compose Animation System a automaticky se pozastavuje při detachmentu.
Spring Animation a Easing křivky (easeInOut, FastOutSlowIn, decelerate) řeší různé úkoly. Easing křivky — matematicky daná trajektorie s pevným časem. Spring — fyzikální simulace, kde čas závisí na parametrech a počátečních podmínkách. Pro jednoduché animace zobrazení/skrytí Easing křivky stačí. Pro animace související s pohybem uživatele (drag, swipe, scroll) poskytuje Spring Animation přirozenější odezvu.
| Scénář | Doporučení | Parametry |
|---|---|---|
| Zobrazení prvku | Spring (damping = 0.7, stiffness = 400) | Plynulé zobrazení s mírným překmitem |
| Swipe-to-dismiss | Spring + počáteční rychlost | setStartVelocity(velocity), damping = 0.5 |
| Animace ikony | Spring (damping = 0.3, stiffness = 600) | Znatelný odraz pro akcentní efekty |
| Fyzika scroll | Spring (systémová) | Nepřizpůsobovat — Android spravuje sám |
| Změna velikosti | Easing (FastOutSlowIn) | Easing je spolehlivější pro změny layoutu |
Anti-patterns: nepoužívejte Spring Animation pro animaci parametrů layoutu (šířka/výška View přes LayoutParams) — to způsobuje přepočet hierarchie v každém snímku, což vede k cukání a poklesu FPS. Pro animaci barvy jsou také lepší Easing křivky. Pro animaci pozice scroll použijte systémový Scroller s fling — Spring Animation zde nenabízí výhody. Pro maximální výkon na Androidu omezte počet současně aktivních SpringAnimation na 10–15.
Často kladené otázky
Stiffness — tuhost pružiny (síla návratu). Vysoká hodnota (1000) — rychlý, prudký pohyb. Nízká (100) — jemný, pomalý. Damping — tlumení (odpor). Nízké (0.2) — dlouhé kmity s odrazem. Vysoké (1.0) — bez kmitů, plynulé zpomalení. Stiffness určuje rychlost, damping — přítomnost a intenzitu kmitů.
Začněte s damping = 0.5 a stiffness = 400 — to je univerzální startovací sada pro iOS a Android. Pro zobrazení prvků zvyšte damping na 0.7. Pro akcentní efekty (like, přidání do košíku) snižte damping na 0.3 s stiffness = 600. Pro Material Motion použijte damping = 0.6 a stiffness = 300. Animaci kontrolujte na reálném zařízení, ne v simulátoru.
Ano, ve SwiftUI se pružinová animace nastavuje pomocí .animation(.spring(dampingFraction: 0.5, response: 0.5), value: state) nebo .spring(blendDuration: 0.3) v withAnimation. response a dampingFraction odpovídají stiffness a damping z UIKit. Pro interactiveSpring() použijte .interactiveSpring() — speciální verze s počáteční rychlostí z gesta, optimalizovaná pro drag animace.
Zkontrolujte SpringForce.finalPosition — pokud není nastavena nebo se rovná aktuální hodnotě, animace nemusí začít. Volejte springAnim.cancel() v onPause() Activity/Fragment. Pro SpringAnimation v RecyclerView použijte view.setOnDetachListener { animator.cancel() }. Pro Jetpack Compose se SpringAnimation automaticky pozastaví při kompozici.
Ano. Na iOS zavolejte view.layer.removeAnimation(forKey:) — animace se zastaví na aktuálním snímku. Na Androidu zavolejte springAnim.cancel() — objekt zůstane na aktuální pozici. Pro plynulý přechod na novou cílovou hodnotu aktualizujte finalPosition a nevolejte cancel — SpringAnimation automaticky přepočítá trajektorii. Pro SkipToEnd použijte springAnim.skipToEnd() na Androidu.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také