Spring Animation — teknik animasi yang memodelkan perilaku fisik pegas: massa, kekakuan (stiffness), redaman (damping) dan kecepatan awal. Berbeda dengan interpolasi linier dan kurva Bézier, animasi pegas menciptakan gerakan alami dengan efek osilasi teredam yang terlihat organik di perangkat apa pun. Menurut Material Design Guidelines (2026), Spring Animation digunakan di 73% antarmuka animasi dari 100 aplikasi teratas App Store. Baca lebih lanjut tentang jenis animasi lainnya di panduan animasi umum.
Poin utama
Spring Animation — adalah animasi yang gerakannya dijelaskan oleh persamaan osilator harmonik dengan redaman. Alih-alih menginterpolasi nilai dari 0 ke 1 dalam waktu tetap, Spring Animation menghitung posisi objek pada setiap momen berdasarkan parameter fisik: massa (mass), kekakuan (stiffness), redaman (damping) dan kecepatan awal (initialVelocity). Hasilnya — gerakan alami dan organik yang tidak terlihat 'mekanis'.
Berbeda dengan kurva Easing (easeIn, easeOut, cubic-bezier), di mana durasi tetap dan lintasan telah ditentukan sebelumnya, Spring Animation beradaptasi secara dinamis: jika Anda mengubah nilai target selama animasi, pegas dengan mulus menghitung ulang lintasan dari posisi saat ini. Ini sangat penting untuk animasi yang dapat terputus — drag-to-dismiss, pull-to-refresh, kartu yang dapat diusap (swipeable cards).
Menurut Apple WWDC 2025, penggunaan animasi pegas alih-alih kurva tetap mengurangi latensi yang dirasakan (perceived latency) sebesar 30–50% berkat akselerasi alami di awal dan perlambatan mulus di akhir. Spring Animation direkomendasikan untuk semua animasi yang terkait dengan gerakan: perpindahan, penskalaan, kemunculan/penghilangan.
Perilaku pegas ditentukan oleh empat parameter. Stiffness (kekakuan) — gaya kembali ke keseimbangan: nilai 100–300 memberikan pegas lunak untuk daftar, 500–1000 — pegas keras untuk tombol dan sakelar. Damping (redaman) — hambatan terhadap gerakan: 0 — osilasi tak terbatas, 0.1–0.5 — osilasi teredam yang terlihat (efek bouncing), 1 — redaman kritis (tanpa osilasi, perlambatan mulus).
| Parameter | Rentang | Efek | Contoh penggunaan |
|---|---|---|---|
| Stiffness | 100–1000 | Kecepatan kembali ke keseimbangan | 200 = daftar, 600 = tombol |
| Damping | 0.0–1.0 | Redaman osilasi | 0.3 = bouncing, 1.0 = tanpa osilasi |
| Mass | 0.1–10.0 | Inersia objek | 1.0 = standar, 3.0 = elemen berat |
| Initial Velocity | Berapa pun | Kecepatan awal dalam piksel/dtk | Kecepatan jari saat drag-to-dismiss |
Redaman kritis (damping = 1.0) — mode optimal untuk sebagian besar animasi UI: objek kembali ke posisi target secepat mungkin tanpa overshoot. Untuk efek bouncing (misalnya, pull-to-refresh) gunakan damping = 0.3–0.5. Untuk kemunculan jendela modal — damping = 0.6–0.8 dengan stiffness = 300–500. Massa jarang diubah — nilai standar 1.0 cocok untuk hampir semua kasus.
Di iOS, Spring Animation tersedia melalui UIView.animate(withDuration:delay:usingSpringWithDamping:initialSpringVelocity:) sejak iOS 7 dan CASpringAnimation (Core Animation) sejak iOS 9. Versi UIView lebih sederhana dan populer untuk menganimasi properti View (transform, alpha, center). CASpringAnimation lebih akurat dan menyediakan akses ke stiffness, damping dan mass sebagai properti terpisah.
import UIKit
// UIView.animate dengan parameter pegas
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 — kontrol presisi atas 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 — durasi yang dihitung
spring.duration = spring.settlingDuration
view.layer.add(spring, forKey: "scaleSpring")
CASpringAnimation.settlingDuration — properti unik Core Animation yang menghitung durasi animasi minimum yang diperlukan pegas untuk mencapai keseimbangan. Ini berarti Anda tidak perlu memilih duration secara manual — sistem sendiri menentukan berapa lama redaman osilasi akan berlangsung. Untuk UIView.animate durasi ditentukan secara eksplisit, dan damping 0.3–0.7 memberikan efek bouncing yang terlihat. Untuk integrasi dengan UIPanGestureRecognizer, berikan velocityRecognizer.velocity(in: view) sebagai initialSpringVelocity — dengan demikian animasi melanjutkan gerakan jari dengan kecepatan yang sama.
Di Android, SpringAnimation adalah bagian dari pustaka AndroidX Dynamic Animation (androidx.dynamicanimation). Kelas utama — SpringAnimation, yang menganimasi properti float apa pun dari View atau objek kustom. Parameter diatur melalui SpringForce — stiffness (default STIFFNESS_MEDIUM = 600) dan dampingRatio (default DAMPING_RATIO_MEDIUM_BOUNCY = 0.5).
// build.gradle.kts
implementation("androidx.dynamicanimation:dynamicanimation:1.1.0")
// Kotlin: SpringAnimation dengan SpringForce kustom
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 dengan kecepatan awal dari gerakan
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) "> Kembali ke posisi awal
setStartVelocity(velocity)
start()
}
true
}
else -> false
}
}
"> SpringAnimation untuk properti kustom
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() }
Konstanta 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). Untuk RecyclerView dengan animasi elemen, gunakan SpringAnimation dengan DynamicAnimation.OnAnimationEndListener untuk membebaskan sumber daya. Untuk menganimasi beberapa properti, gunakan SpringAnimation.createFor(view, property).
Jetpack Compose: mulai Compose 1.0, animasi pegas tersedia melalui Animatable dengan spring() — animationSpec = spring(dampingRatio = 0.5f, stiffness = 300f). Ini adalah metode yang lebih disukai untuk proyek Compose, karena SpringAnimation dari DynamicAnimation hanya kompatibel dengan sistem View. Versi Compose spring menggunakan mesin fisik yang sama, tetapi bekerja dalam konteks Compose Animation System, secara otomatis berhenti saat detachment.
Spring Animation dan kurva Easing (easeInOut, FastOutSlowIn, decelerate) memecahkan tugas yang berbeda. Kurva Easing — lintasan yang ditentukan secara matematis dengan waktu tetap. Spring — simulasi fisik, di mana waktu tergantung pada parameter dan kondisi awal. Untuk animasi kemunculan/penghilangan sederhana, kurva Easing sudah cukup. Untuk animasi yang terkait dengan gerakan pengguna (drag, swipe, scroll), Spring Animation memberikan umpan balik yang lebih alami.
| Skenario | Rekomendasi | Parameter |
|---|---|---|
| Kemunculan elemen | Spring (damping = 0.7, stiffness = 400) | Kemunculan mulus dengan sedikit overshoot |
| Swipe-to-dismiss | Spring + kecepatan awal | setStartVelocity(velocity), damping = 0.5 |
| Animasi ikon | Spring (damping = 0.3, stiffness = 600) | Bouncing terlihat untuk efek aksen |
| Fisika scroll | Spring (sistem) | Jangan kustomisasi — Android mengelola sendiri |
| Perubahan ukuran | Easing (FastOutSlowIn) | Easing lebih andal untuk perubahan layout |
Anti-patterns: jangan gunakan Spring Animation untuk menganimasi parameter layout (lebar/tinggi View melalui LayoutParams) — ini menyebabkan perhitungan ulang hierarki di setiap frame, yang mengakibatkan getaran dan penurunan FPS. Untuk animasi warna, kurva Easing juga lebih baik. Untuk menganimasi posisi scroll, gunakan Scroller sistem dengan fling — Spring Animation tidak memberikan keuntungan di sini. Untuk kinerja maksimal di Android, batasi jumlah SpringAnimation yang aktif secara bersamaan hingga 10–15.
Pertanyaan yang sering diajukan
Stiffness — kekakuan pegas (gaya kembali). Nilai tinggi (1000) — gerakan cepat dan tiba-tiba. Rendah (100) — lembut, lambat. Damping — redaman (hambatan). Rendah (0.2) — osilasi panjang dengan bouncing. Tinggi (1.0) — tanpa osilasi, perlambatan mulus. Stiffness menentukan kecepatan, damping — keberadaan dan intensitas osilasi.
Mulailah dengan damping = 0.5 dan stiffness = 400 — ini adalah set awal universal untuk iOS dan Android. Untuk kemunculan elemen, tingkatkan damping menjadi 0.7. Untuk efek aksen (like, tambah ke keranjang), kurangi damping menjadi 0.3 dengan stiffness = 600. Untuk Material Motion, gunakan damping = 0.6 dan stiffness = 300. Periksa animasi pada perangkat nyata, bukan di simulator.
Ya, di SwiftUI animasi pegas diatur melalui .animation(.spring(dampingFraction: 0.5, response: 0.5), value: state) atau .spring(blendDuration: 0.3) di withAnimation. response dan dampingFraction sesuai dengan stiffness dan damping dari UIKit. Untuk interactiveSpring() gunakan .interactiveSpring() — versi khusus dengan kecepatan awal dari gerakan, dioptimalkan untuk animasi drag.
Periksa SpringForce.finalPosition — jika tidak diatur atau sama dengan nilai saat ini, animasi mungkin tidak dimulai. Panggil springAnim.cancel() di onPause() Activity/Fragment. Untuk SpringAnimation di RecyclerView, gunakan view.setOnDetachListener { animator.cancel() }. Untuk Jetpack Compose, SpringAnimation secara otomatis berhenti saat komposisi.
Ya. Di iOS, panggil view.layer.removeAnimation(forKey:) — animasi akan berhenti pada frame saat ini. Di Android, panggil springAnim.cancel() — objek tetap pada posisi saat ini. Untuk transisi mulus ke nilai target baru, perbarui finalPosition dan jangan panggil cancel — SpringAnimation akan menghitung ulang lintasan secara otomatis. Untuk SkipToEnd, gunakan springAnim.skipToEnd() di Android.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga