Spring Animation — teknik ng animation na nagmomodelo ng pisikal na pag-uugali ng spring: masa, tigas (stiffness), damping (pagpigil) at paunang bilis. Hindi tulad ng mga linear interpolation at Bezier curves, ang spring animation ay lumilikha ng natural na paggalaw na may epekto ng lumilipas na mga oscillation na mukhang organic sa anumang device. Ayon sa Material Design Guidelines (2026), ang Spring Animation ay ginagamit sa 73% ng mga animated na interface ng top 100 App Store apps. Magbasa pa tungkol sa iba pang uri ng animation sa pangkalahatang gabay sa animation.
Mga pangunahing punto
Spring Animation — ay isang animation na ang paggalaw ay inilalarawan ng equation ng harmonic oscillator na may damping. Sa halip na i-interpolate ang halaga mula 0 hanggang 1 sa isang takdang oras, kinakalkula ng Spring Animation ang posisyon ng object sa bawat sandali batay sa mga pisikal na parameter: masa (mass), tigas (stiffness), damping (pagpigil) at paunang bilis (initialVelocity). Ang resulta — natural, organikong paggalaw na hindi mukhang 'mekanikal'.
Hindi tulad ng Easing curves (easeIn, easeOut, cubic-bezier), kung saan ang tagal ay takda at ang trajectory ay paunang natukoy, ang Spring Animation ay dinamikong umaangkop: kung babaguhin mo ang target na halaga sa panahon ng animation, ang spring ay maayos na muling kakakalkula ng trajectory mula sa kasalukuyang posisyon. Ito ay lalong mahalaga para sa mga animation na maaaring maantala — drag-to-dismiss, pull-to-refresh, mga card na maaaring i-swipe (swipeable cards).
Ayon sa Apple WWDC 2025, ang paggamit ng spring animation sa halip ng mga fixed curves ay nagbabawas ng perceived latency ng 30–50% dahil sa natural na acceleration sa simula at maayos na pagbagal sa dulo. Ang Spring Animation ay inirerekomenda para sa lahat ng animation na may kaugnayan sa paggalaw: paglipat, pag-scale, paglitaw/paglaho.
Ang pag-uugali ng spring ay tinutukoy ng apat na parameter. Stiffness (tigas) — puwersa ng pagbalik sa equilibrium: halaga 100–300 ay nagbibigay ng malambot na spring para sa mga listahan, 500–1000 — matigas na spring para sa mga button at switch. Damping (pagpigil) — resistensya sa paggalaw: 0 — walang hanggang oscillation, 0.1–0.5 — kapansin-pansing lumilipas na oscillation (bounce effect), 1 — kritikal na damping (walang oscillation, maayos na pagbagal).
| Parameter | Saklaw | Epekto | Halimbawa ng paggamit |
|---|---|---|---|
| Stiffness | 100–1000 | Bilis ng pagbalik sa equilibrium | 200 = listahan, 600 = button |
| Damping | 0.0–1.0 | Pagpigil ng oscillation | 0.3 = bounce, 1.0 = walang oscillation |
| Mass | 0.1–10.0 | Inertia ng object | 1.0 = standard, 3.0 = mabigat na elemento |
| Initial Velocity | Kahit ano | Paunang bilis sa pixels/s | Bilis ng daliri sa drag-to-dismiss |
Kritikal na damping (damping = 1.0) — ang optimal na mode para sa karamihan ng UI animations: ang object ay bumabalik sa target na posisyon nang pinakamabilis nang walang overshoot. Para sa bounce effect (hal. pull-to-refresh) gumamit ng damping = 0.3–0.5. Para sa paglitaw ng modal windows — damping = 0.6–0.8 na may stiffness = 300–500. Ang masa ay bihirang baguhin — ang standard na halaga na 1.0 ay angkop para sa halos lahat ng kaso.
Sa iOS, ang Spring Animation ay available sa pamamagitan ng UIView.animate(withDuration:delay:usingSpringWithDamping:initialSpringVelocity:) mula noong iOS 7 at CASpringAnimation (Core Animation) mula noong iOS 9. Ang UIView na bersyon ay mas simple at mas sikat para sa pag-animate ng mga property ng View (transform, alpha, center). Ang CASpringAnimation ay mas tumpak at nagbibigay ng access sa stiffness, damping at mass bilang mga hiwalay na property.
import UIKit
// UIView.animate na may 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 — tumpak na kontrol sa mga parameter
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 — kinakalkulang tagal
spring.duration = spring.settlingDuration
view.layer.add(spring, forKey: "scaleSpring")
CASpringAnimation.settlingDuration — isang natatanging property ng Core Animation na kinakalkula ang minimum na tagal ng animation na kailangan ng spring upang maabot ang equilibrium. Ibig sabihin hindi mo kailangang pumili ng duration nang manu-mano — ang sistema mismo ang nagtatakda kung gaano katagal ang pagpigil ng oscillation. Para sa UIView.animate ang tagal ay tahasang tinukoy, at ang damping 0.3–0.7 ay nagbibigay ng kapansin-pansing bounce effect. Para sa pagsasama sa UIPanGestureRecognizer, ipasa ang velocityRecognizer.velocity(in: view) bilang initialSpringVelocity — sa ganitong paraan ang animation ay nagpapatuloy ng paggalaw ng daliri sa parehong bilis.
Sa Android, ang SpringAnimation ay bahagi ng AndroidX Dynamic Animation library (androidx.dynamicanimation). Ang pangunahing class — SpringAnimation, na nag-a-animate ng anumang float property ng View o custom na object. Ang mga parameter ay itinakda sa pamamagitan ng SpringForce — stiffness (default STIFFNESS_MEDIUM = 600) at dampingRatio (default DAMPING_RATIO_MEDIUM_BOUNCY = 0.5).
// build.gradle.kts
implementation("androidx.dynamicanimation:dynamicanimation:1.1.0")
// Kotlin: SpringAnimation na may custom na 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 na may paunang bilis mula sa kilos
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) "> Pagbabalik sa orihinal na posisyon
setStartVelocity(velocity)
start()
}
true
}
else -> false
}
}
"> SpringAnimation para sa custom na 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() }
Mga constant ng 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). Para sa RecyclerView na may animation ng elemento, gamitin ang SpringAnimation na may DynamicAnimation.OnAnimationEndListener para sa pagpapalaya ng resources. Para sa pag-animate ng maraming property, gamitin ang SpringAnimation.createFor(view, property).
Jetpack Compose: simula sa Compose 1.0, ang spring animation ay available sa pamamagitan ng Animatable na may spring() — animationSpec = spring(dampingRatio = 0.5f, stiffness = 300f). Ito ang mas pinipiling paraan para sa mga Compose project, dahil ang SpringAnimation mula sa DynamicAnimation ay compatible lamang sa View system. Ang Compose na bersyon spring ay gumagamit ng parehong pisikal na engine, ngunit gumagana sa konteksto ng Compose Animation System, awtomatikong humihinto sa detachment.
Spring Animation at Easing curves (easeInOut, FastOutSlowIn, decelerate) ay lumulutas ng iba't ibang gawain. Easing curves — isang mathematically tinukoy na trajectory na may takdang oras. Spring — pisikal na simulation, kung saan ang oras ay nakasalalay sa mga parameter at paunang kondisyon. Para sa simpleng paglitaw/paglaho ng mga animation, sapat na ang Easing curves. Para sa mga animation na may kaugnayan sa paggalaw ng user (drag, swipe, scroll), ang Spring Animation ay nagbibigay ng mas natural na feedback.
| Scenario | Rekomendasyon | Parameters |
|---|---|---|
| Paglitaw ng elemento | Spring (damping = 0.7, stiffness = 400) | Maayos na paglitaw na may bahagyang overshoot |
| Swipe-to-dismiss | Spring + paunang bilis | setStartVelocity(velocity), damping = 0.5 |
| Animation ng icon | Spring (damping = 0.3, stiffness = 600) | Kapansin-pansing bounce para sa accent effect |
| Pisika ng scroll | Spring (sistema) | Huwag i-customize — Android mismo ang namamahala |
| Pagbabago ng laki | Easing (FastOutSlowIn) | Ang Easing ay mas maaasahan para sa mga pagbabago sa layout |
Anti-patterns: huwag gamitin ang Spring Animation para sa pag-animate ng mga parameter ng layout (lapad/taas ng View sa pamamagitan ng LayoutParams) — ito ay nagdudulot ng muling pagkalkula ng hierarchy sa bawat frame, na humahantong sa panginginig at pagbaba ng FPS. Para sa animation ng kulay, ang Easing curves ay mas mahusay din. Para sa pag-animate ng scroll position, gamitin ang system Scroller na may fling — ang Spring Animation ay hindi nagbibigay ng kalamangan dito. Para sa maximum na performance sa Android, limitahan ang bilang ng sabay-sabay na aktibong SpringAnimation sa 10–15.
Mga madalas itanong
Stiffness — tigas ng spring (puwersa ng pagbalik). Mataas na halaga (1000) — mabilis, biglaang paggalaw. Mababa (100) — malambot, mabagal. Damping — pagpigil (resistensya). Mababa (0.2) — mahabang oscillation na may bounce. Mataas (1.0) — walang oscillation, maayos na pagbagal. Tinutukoy ng Stiffness ang bilis, ng damping — ang pagkakaroon at intensity ng oscillation.
Magsimula sa damping = 0.5 at stiffness = 400 — ito ay isang unibersal na panimulang set para sa iOS at Android. Para sa paglitaw ng mga elemento, taasan ang damping sa 0.7. Para sa accent effect (like, idagdag sa cart), bawasan ang damping sa 0.3 na may stiffness = 600. Para sa Material Motion, gamitin ang damping = 0.6 at stiffness = 300. Suriin ang animation sa isang tunay na device, hindi sa simulator.
Oo, sa SwiftUI ang spring animation ay itinatakda sa pamamagitan ng .animation(.spring(dampingFraction: 0.5, response: 0.5), value: state) o .spring(blendDuration: 0.3) sa withAnimation. Ang response at dampingFraction ay katumbas ng stiffness at damping mula sa UIKit. Para sa interactiveSpring() gamitin ang .interactiveSpring() — isang espesyal na bersyon na may paunang bilis mula sa kilos, na-optimize para sa drag animation.
Suriin ang SpringForce.finalPosition — kung hindi ito nakatakda o katumbas ng kasalukuyang halaga, maaaring hindi magsimula ang animation. Tawagin ang springAnim.cancel() sa onPause() ng Activity/Fragment. Para sa SpringAnimation sa RecyclerView, gamitin ang view.setOnDetachListener { animator.cancel() }. Para sa Jetpack Compose, awtomatikong humihinto ang SpringAnimation sa composition.
Oo. Sa iOS, tawagin ang view.layer.removeAnimation(forKey:) — ang animation ay hihinto sa kasalukuyang frame. Sa Android, tawagin ang springAnim.cancel() — ang object ay mananatili sa kasalukuyang posisyon. Para sa maayos na paglipat sa bagong target na halaga, i-update ang finalPosition at huwag tawagin ang cancel — awtomatikong muling kakakalkula ng SpringAnimation ang trajectory. Para sa SkipToEnd, gamitin ang springAnim.skipToEnd() sa Android.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din