Gerakan berbasis fisika didorong oleh gaya. Gaya pegas adalah salah satu gaya yang memandu interaktivitas dan gerakan. Gaya pegas memiliki sifat berikut: redaman dan kekakuan. Pada animasi berbasis pegas, nilai dan kecepatan dihitung berdasarkan gaya pegas yang diterapkan pada setiap frame.
Jika Anda ingin animasi aplikasi melambat hanya dalam satu arah, pertimbangkan untuk menggunakan animasi fling berbasis gesekan.
Siklus animasi pegas
Pada animasi berbasis pegas, class SpringForce
memungkinkan Anda menyesuaikan kekakuan pegas, rasio redaman, dan
posisi akhirnya. Segera setelah animasi dimulai, gaya pegas akan memperbarui nilai animasi dan kecepatan di setiap frame. Animasi ini berlanjut hingga gaya pegas mencapai kesetimbangan.
Misalnya, jika Anda menarik ikon aplikasi mengitari layar, lalu melepaskannya dengan mengangkat jari dari ikon, ikon akan kembali ke tempat semula dengan gaya yang tak terlihat, tetapi sudah dikenali.
Gambar 1 memperlihatkan efek pegas yang serupa. Tanda plus (+) di tengah lingkaran menunjukkan gaya yang diterapkan melalui gestur sentuh.
Membuat animasi pegas
Langkah-langkah umum untuk membuat animasi pegas untuk aplikasi Anda adalah sebagai berikut:
- Menambahkan support library Anda harus menambahkan support library ke project untuk menggunakan class animasi pegas.
- Membuat animasi pegas:
Langkah utama adalah membuat instance class
SpringAnimation
dan menetapkan parameter perilaku gerakan. - (Opsional) Mendaftarkan pemroses: Daftarkan pemroses yang akan memantau perubahan siklus proses animasi dan pembaruan nilai animasi.
Catatan: Pemroses pembaruan sebaiknya didaftarkan hanya jika Anda memerlukan pembaruan per frame terkait perubahan nilai animasi. Pemroses update mencegah animasi berpotensi berjalan di thread terpisah.
- (Opsional) Menghapus pemroses: Hapus pemroses yang tidak lagi digunakan.
- (Opsional) Menetapkan nilai awal: Sesuaikan nilai awal animasi.
- (Opsional) Menetapkan rentang nilai: Tetapkan rentang nilai animasi untuk membatasi nilai dalam rentang minimum dan maksimum.
- (Opsional) Menetapkan kecepatan awal: Tetapkan kecepatan awal untuk animasi.
- (Opsional) Menetapkan properti pegas: Tetapkan rasio redaman dan kekakuan pegas.
- (Opsional) Buat pegas kustom: Buat pegas kustom jika Anda tidak ingin menggunakan pegas default atau ingin menggunakan pegas umum di seluruh animasi.
- Memulai animasi: Memulai animasi pegas.
- (Opsional) Membatalkan animasi: Batalkan animasi jika pengguna tiba-tiba keluar dari aplikasi atau tampilan menjadi tidak terlihat.
Bagian berikut membahas langkah-langkah umum untuk membuat animasi pegas secara mendetail.
Menambahkan support library
Untuk menggunakan support library berbasis fisika, Anda harus menambahkan support library tersebut ke project Anda sebagai berikut:
- Buka file
build.gradle
untuk modul aplikasi Anda. Tambahkan support library ke bagian
dependencies
.Groovy
dependencies { def dynamicanimation_version = '1.0.0' implementation "androidx.dynamicanimation:dynamicanimation:$dynamicanimation_version" }
Kotlin
dependencies { val dynamicanimation_version = "1.0.0" implementation("androidx.dynamicanimation:dynamicanimation:$dynamicanimation_version") }
Untuk melihat versi terbaru library ini, lihat informasi tentang DynamicAnimation di halaman versi.
Membuat animasi pegas
Class SpringAnimation
memungkinkan Anda membuat animasi pegas untuk sebuah objek. Untuk membuat animasi pegas, Anda harus membuat instance class SpringAnimation
dan menyediakan sebuah objek, properti objek yang ingin dianimasikan, dan posisi pegas akhir opsional di mana Anda ingin animasi berhenti.
Catatan: Pada saat membuat animasi pegas, posisi akhir pegas bersifat opsional. Namun, hal ini harus ditentukan sebelum memulai animasi.
Kotlin
val springAnim = findViewById<View>(R.id.imageView).let { img -> // Setting up a spring animation to animate the view’s translationY property with the final // spring position at 0. SpringAnimation(img, DynamicAnimation.TRANSLATION_Y, 0f) }
Java
final View img = findViewById(R.id.imageView); // Setting up a spring animation to animate the view’s translationY property with the final // spring position at 0. final SpringAnimation springAnim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y, 0);
Animasi berbasis pegas dapat menganimasikan tampilan di layar dengan mengubah properti sebenarnya dalam objek tampilan. Tampilan berikut tersedia di sistem:
ALPHA
: Menampilkan transparansi alfa pada tampilan. Nilainya adalah 1 (buram) secara default, dengan nilai 0 menunjukkan transparansi penuh (tidak terlihat).TRANSLATION_X
,TRANSLATION_Y
, danTRANSLATION_Z
: Properti ini mengontrol lokasi tampilan sebagai delta dari koordinat kiri, koordinat atas, dan elevasi, yang ditetapkan oleh container tata letaknya.TRANSLATION_X
mendeskripsikan koordinat kiri.TRANSLATION_Y
mendeskripsikan koordinat teratas.TRANSLATION_Z
mendeskripsikan kedalaman tampilan relatif terhadap elevasinya.
ROTATION
,ROTATION_X
, danROTATION_Y
: Properti ini mengontrol rotasi dalam 2D (propertirotation
) dan 3D di sekitar titik pivot.SCROLL_X
danSCROLL_Y
: Properti ini menunjukkan offset scroll tepi kiri dan atas sumber dalam piksel. Juga menunjukkan posisi dalam hal seberapa banyak halaman di-scroll.SCALE_X
danSCALE_Y
: Properti ini mengontrol penskalaan 2D tampilan di sekitar titik pivotnya.X
,Y
, danZ
: Ini adalah properti utilitas dasar untuk mendeskripsikan lokasi akhir tampilan dalam container-nya.X
adalah jumlah dari nilai kiri danTRANSLATION_X
.Y
adalah jumlah dari nilai teratas danTRANSLATION_Y
.Z
adalah jumlah dari nilai elevasi danTRANSLATION_Z
.
Mendaftarkan pemroses
Class DynamicAnimation
menyediakan dua
pemroses: OnAnimationUpdateListener
dan OnAnimationEndListener
.
Pemroses ini memproses pembaruan dalam animasi, misalnya saat ada perubahan nilai animasi dan saat animasi berakhir.
OnAnimationUpdateListener
Jika ingin menganimasikan beberapa tampilan untuk membuat animasi berantai, Anda dapat menyiapkan OnAnimationUpdateListener
untuk menerima callback setiap kali ada perubahan pada properti tampilan saat ini. Callback memberi tahu tampilan lain untuk memperbarui posisi pegasnya berdasarkan perubahan yang terjadi dalam properti tampilan saat ini. Untuk mendaftarkan pemroses, lakukan langkah-langkah berikut:
-
Panggil metode
addUpdateListener()
dan pasang pemroses ke animasi.Catatan: Anda harus mendaftarkan pemroses pembaruan sebelum animasi dimulai. Namun, pemroses pembaruan sebaiknya didaftarkan hanya jika Anda memerlukan pembaruan per frame terkait perubahan nilai animasi. Pemroses update mencegah animasi berpotensi berjalan di thread terpisah.
-
Ganti metode
onAnimationUpdate()
untuk memberi tahu pemanggil tentang perubahan pada objek saat ini. Kode contoh berikut mengilustrasikan penggunaanOnAnimationUpdateListener
secara keseluruhan.
Kotlin
// Setting up a spring animation to animate the view1 and view2 translationX and translationY properties val (anim1X, anim1Y) = findViewById<View>(R.id.view1).let { view1 -> SpringAnimation(view1, DynamicAnimation.TRANSLATION_X) to SpringAnimation(view1, DynamicAnimation.TRANSLATION_Y) } val (anim2X, anim2Y) = findViewById<View>(R.id.view2).let { view2 -> SpringAnimation(view2, DynamicAnimation.TRANSLATION_X) to SpringAnimation(view2, DynamicAnimation.TRANSLATION_Y) } // Registering the update listener anim1X.addUpdateListener { _, value, _ -> // Overriding the method to notify view2 about the change in the view1’s property. anim2X.animateToFinalPosition(value) } anim1Y.addUpdateListener { _, value, _ -> anim2Y.animateToFinalPosition(value) }
Java
// Creating two views to demonstrate the registration of the update listener. final View view1 = findViewById(R.id.view1); final View view2 = findViewById(R.id.view2); // Setting up a spring animation to animate the view1 and view2 translationX and translationY properties final SpringAnimation anim1X = new SpringAnimation(view1, DynamicAnimation.TRANSLATION_X); final SpringAnimation anim1Y = new SpringAnimation(view1, DynamicAnimation.TRANSLATION_Y); final SpringAnimation anim2X = new SpringAnimation(view2, DynamicAnimation.TRANSLATION_X); final SpringAnimation anim2Y = new SpringAnimation(view2, DynamicAnimation.TRANSLATION_Y); // Registering the update listener anim1X.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() { // Overriding the method to notify view2 about the change in the view1’s property. @Override public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float value, float velocity) { anim2X.animateToFinalPosition(value); } }); anim1Y.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() { @Override public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float value, float velocity) { anim2Y.animateToFinalPosition(value); } });
OnAnimationEndListener
OnAnimationEndListener
memberi tahu akhir animasi. Anda dapat menyiapkan pemroses untuk menerima callback setiap kali animasi mencapai kesetimbangan atau dibatalkan. Untuk
mendaftarkan pemroses, lakukan langkah-langkah berikut:
-
Panggil metode
addEndListener()
dan pasang pemroses ke animasi. -
Ganti metode
onAnimationEnd()
untuk menerima notifikasi setiap kali animasi mencapai kesetimbangan atau dibatalkan.
Menghapus pemroses
Untuk berhenti menerima callback pembaruan animasi dan callback akhir animasi, panggil metode removeUpdateListener()
dan removeEndListener()
.
Menetapkan nilai awal animasi
Untuk menetapkan nilai awal animasi, panggil metode setStartValue()
dan teruskan nilai awal animasi. Jika nilai awal tidak ditetapkan, animasi akan menggunakan nilai properti objek saat ini sebagai nilai awal.
Menetapkan rentang nilai animasi
Anda dapat menetapkan nilai animasi minimum dan maksimum jika ingin membatasi nilai properti ke rentang tertentu. Ada baiknya juga mengontrol rentang jika Anda menganimasikan properti yang memiliki rentang intrinsik, seperti alfa (dari 0 hingga 1).
-
Untuk menetapkan nilai minimum, panggil metode
setMinValue()
dan teruskan nilai minimum properti. -
Untuk menetapkan nilai maksimum, panggil metode
setMaxValue()
dan teruskan nilai maksimum properti.
Kedua metode ini menampilkan animasi yang nilainya ditetapkan.
Catatan: Jika Anda telah menetapkan nilai awal dan menentukan rentang nilai animasi, pastikan nilai awal berada dalam rentang nilai minimum dan maksimum.
Menetapkan kecepatan awal
Kecepatan awal menentukan kecepatan perubahan properti animasi di awal animasi. Kecepatan awal default ditetapkan ke nol piksel per detik. Anda dapat mengatur kecepatan dengan kecepatan gestur sentuh atau dengan menggunakan nilai tetap sebagai kecepatan awal. Jika Anda memilih untuk memberikan nilai tetap, sebaiknya tentukan nilai tersebut dalam dp per detik, lalu konversikan menjadi piksel per detik. Dengan menentukan nilai dalam dp per detik, kecepatan menjadi tidak bergantung pada kepadatan dan faktor bentuk. Untuk mengetahui informasi selengkapnya tentang mengonversi nilai menjadi piksel per detik, lihat bagian Mengonversi dp per detik menjadi piksel per detik.
Untuk menetapkan kecepatan, panggil metode
setStartVelocity()
dan teruskan kecepatan dalam piksel per detik. Metode ini menampilkan objek gaya pegas yang kecepatannya ditetapkan.
Catatan: Gunakan metode class
GestureDetector.OnGestureListener
atau
VelocityTracker
untuk mengambil dan menghitung
kecepatan gestur sentuh.
Kotlin
findViewById<View>(R.id.imageView).also { img -> SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply { … // Compute velocity in the unit pixel/second vt.computeCurrentVelocity(1000) val velocity = vt.yVelocity setStartVelocity(velocity) } }
Java
final View img = findViewById(R.id.imageView); final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y); … // Compute velocity in the unit pixel/second vt.computeCurrentVelocity(1000); float velocity = vt.getYVelocity(); anim.setStartVelocity(velocity);
Mengonversi dp per detik menjadi piksel per detik
Kecepatan pegas harus ditetapkan dalam piksel per detik. Jika Anda memilih untuk memberikan nilai tetap sebagai awal kecepatan, berikan nilai tersebut dalam dp per detik, lalu konversikan menjadi piksel per detik. Untuk konversi, gunakan metode
applyDimension()
dari class TypedValue
. Lihat
kode contoh berikut:
Kotlin
val pixelPerSecond: Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpPerSecond, resources.displayMetrics)
Java
float pixelPerSecond = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpPerSecond, getResources().getDisplayMetrics());
Menetapkan properti pegas
Class SpringForce
menentukan metode pengambil dan penyetel untuk setiap properti pegas, seperti rasio redaman dan kekakuan. Untuk menetapkan properti pegas, penting untuk mengambil objek gaya pegas atau membuat gaya pegas kustom yang dapat Anda gunakan untuk menetapkan properti. Untuk informasi selengkapnya tentang membuat gaya pegas kustom, lihat bagian Membuat gaya pegas kustom.
Tips: Saat menggunakan metode penyetel, Anda dapat membuat rantai metode karena semua metode penyetel menampilkan objek gaya pegas.
Rasio redaman
Rasio redaman menjelaskan berkurangnya ayunan pegas secara bertahap. Dengan rasio redaman, Anda dapat menentukan seberapa cepat ayunan meluncur dari satu pantulan ke pantulan berikutnya. Ada empat cara untuk meredam pegas:
- Overdamping (peredaman berlebih) terjadi jika rasio redaman lebih besar daripada satu. Hal ini memungkinkan objek kembali ke posisi diam dengan lembut.
- Peredaman kritis terjadi jika rasio redaman sama dengan satu. Akibatnya, objek dapat kembali ke posisi istirahat dalam waktu tersingkat.
- Underdamping terjadi jika rasio redaman kurang dari satu. Akibatnya, objek melejit beberapa kali dengan meneruskan posisi diam, lalu secara bertahap mencapai posisi diam.
- Tanpa redaman terjadi jika rasio redaman sama dengan nol. Akibatnya, objek dapat berosilasi selamanya.
Untuk menambahkan rasio redaman ke pegas, lakukan langkah-langkah berikut:
-
Panggil metode
getSpring()
untuk mengambil pegas yang akan menambahkan rasio redaman. -
Panggil metode
setDampingRatio()
dan teruskan rasio redaman yang ingin Anda tambahkan ke pegas. Metode ini menampilkan objek gaya pegas yang rasio peredamannya ditetapkan.Catatan: Rasio redaman harus berupa angka selain negatif. Jika Anda menetapkan rasio redaman ke nol, pegas tidak akan pernah mencapai posisi diam. Dengan kata lain, pegas terus-menerus berayun.
Konstanta rasio redaman berikut tersedia dalam sistem:
DAMPING_RATIO_HIGH_BOUNCY
DAMPING_RATIO_MEDIUM_BOUNCY
DAMPING_RATIO_LOW_BOUNCY
DAMPING_RATIO_NO_BOUNCY
Gambar 2: Pantulan tinggi
Gambar 3: Pantulan sedang
Gambar 4: Pantulan rendah
Gambar 5: Tanpa pantulan
Rasio redaman default ditetapkan ke DAMPING_RATIO_MEDIUM_BOUNCY
.
Kotlin
findViewById<View>(R.id.imageView).also { img -> SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply { … // Setting the damping ratio to create a low bouncing effect. spring.dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY … } }
Java
final View img = findViewById(R.id.imageView); final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y); … // Setting the damping ratio to create a low bouncing effect. anim.getSpring().setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY); …
Kekakuan
Kekakuan menentukan konstanta pegas, yang mengukur kekuatan pegas. Pegas kaku memberikan gaya lebih besar ke objek yang terpasang saat pegas tidak berada di posisi diam. Untuk menambahkan kekakuan ke pegas, lakukan langkah-langkah berikut:
-
Panggil metode
getSpring()
untuk mengambil pegas guna menambah kekakuan. -
Panggil metode
setStiffness()
dan teruskan nilai kekakuan yang ingin Anda tambahkan ke pegas. Metode ini menampilkan objek gaya pegas yang kekakuannya ditetapkan.Catatan: Kekakuan harus berupa bilangan positif.
Konstanta kekakuan berikut tersedia dalam sistem:
Gambar 6: Kekakuan tinggi
Gambar 7: Kekakuan sedang
Gambar 8: Kekakuan rendah
Gambar 9: Kekakuan sangat rendah
Kekakuan default disetel ke STIFFNESS_MEDIUM
.
Kotlin
findViewById<View>(R.id.imageView).also { img -> SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply { … // Setting the spring with a low stiffness. spring.stiffness = SpringForce.STIFFNESS_LOW … } }
Java
final View img = findViewById(R.id.imageView); final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y); … // Setting the spring with a low stiffness. anim.getSpring().setStiffness(SpringForce.STIFFNESS_LOW); …
Membuat gaya pegas kustom
Anda dapat membuat gaya pegas kustom sebagai alternatif dari menggunakan gaya pegas default. Gaya pegas kustom memungkinkan Anda berbagi instance gaya pegas yang sama di beberapa animasi pegas. Setelah membuat gaya pegas, Anda dapat menetapkan properti seperti rasio redaman dan kekakuan.
-
Buat objek
SpringForce
.SpringForce force = new SpringForce();
-
Tetapkan properti dengan memanggil metode yang terkait. Anda juga dapat
membuat rantai metode.
force.setDampingRatio(DAMPING_RATIO_LOW_BOUNCY).setStiffness(STIFFNESS_LOW);
-
Panggil metode
setSpring()
untuk menetapkan pegas ke animasi.setSpring(force);
Memulai animasi
Ada dua cara untuk memulai animasi pegas: Dengan memanggil start()
atau dengan memanggil metode animateToFinalPosition()
. Kedua metode ini harus dipanggil di thread utama.
Metode animateToFinalPosition()
menjalankan dua tugas:
- Menetapkan posisi akhir pegas.
- Memulai animasi, jika belum dimulai.
Karena metode ini memperbarui posisi akhir pegas dan memulai animasi jika perlu, Anda dapat memanggil metode ini kapan saja untuk mengubah arah animasi. Misalnya, dalam animasi pegas berantai, animasi satu tampilan bergantung pada tampilan lainnya. Untuk animasi seperti itu, akan lebih
praktis untuk menggunakan metode
animateToFinalPosition()
. Dengan menggunakan metode ini dalam animasi pegas berantai, Anda tidak perlu
khawatir jika animasi yang ingin Anda perbarui berikutnya sedang berjalan.
Gambar 10 mengilustrasikan animasi pegas berantai, dengan animasi satu tampilan bergantung pada tampilan lainnya.
Untuk menggunakan metode animateToFinalPosition()
, panggil metode animateToFinalPosition()
dan teruskan posisi pegas yang tersisa. Anda juga dapat menetapkan posisi sisanya dari pegas dengan memanggil metode setFinalPosition()
.
Metode start()
tidak langsung menetapkan nilai properti ke nilai awal. Nilai properti berubah pada setiap denyut animasi, yang terjadi sebelum operasi gambar diteruskan.
Akibatnya, perubahan tersebut tercermin dalam frame berikutnya, seolah-olah
nilai ditetapkan dengan segera.
Kotlin
findViewById<View>(R.id.imageView).also { img -> SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply { … // Starting the animation start() … } }
Java
final View img = findViewById(R.id.imageView); final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y); … // Starting the animation anim.start(); …
Membatalkan animasi
Anda dapat membatalkan atau melompat ke bagian akhir animasi. Situasi ideal di mana Anda perlu membatalkan atau melewati ke akhir animasi adalah ketika interaksi pengguna meminta animasi dihentikan segera. Masalah ini utamanya terjadi saat pengguna tiba-tiba keluar dari aplikasi atau tampilan menjadi tidak terlihat.
Ada dua metode yang dapat Anda gunakan untuk menghentikan animasi.
Metode cancel()
mengakhiri animasi pada nilai tempatnya berada. Metode skipToEnd()
melewati animasi ke nilai akhir, lalu menghentikannya.
Sebelum Anda dapat menghentikan animasi, penting untuk memeriksa status pegas terlebih dahulu. Jika status tanpa pengurangan, animasi tidak akan pernah mencapai posisi istirahat.
Untuk memeriksa status pegas, panggil metode canSkipToEnd()
. Jika pegas diredam, metode akan menampilkan true
, jika tidak, false
.
Setelah mengetahui status pegas, Anda dapat menghentikan animasi menggunakan metode skipToEnd()
atau metode cancel()
. Metode
cancel()
harus hanya dipanggil pada thread utama.
Catatan: Secara umum, metode
skipToEnd()
menyebabkan
lompatan visual.