Sistem animasi properti adalah framework andal yang memungkinkan Anda menganimasikan hampir semua hal. Anda dapat menentukan animasi untuk mengubah properti objek apa pun dari waktu ke waktu, terlepas dari apakah animasi tersebut menarik ke layar atau tidak. Animasi properti mengubah nilai properti (kolom dalam objek) selama jangka waktu tertentu. Untuk menganimasikan sesuatu, Anda menentukan properti objek yang ingin dianimasikan, seperti posisi objek di layar, berapa lama Anda ingin menganimasikannya, dan nilai apa yang ingin Anda animasikan.
Sistem animasi properti memungkinkan Anda menentukan karakteristik animasi berikut:
- Durasi: Anda dapat menentukan durasi animasi. Durasi defaultnya adalah 300 milidetik.
- Jenis interpolasi waktu: Anda dapat menentukan cara nilai untuk properti dihitung sebagai fungsi dari waktu berlalu saat ini untuk animasi tersebut.
- Jumlah dan perilaku pengulangan: Anda dapat menentukan apakah akan mengulang animasi atau tidak saat mencapai akhir durasi dan berapa kali animasi akan diulang. Anda juga dapat menentukan apakah animasi akan diputar terbalik atau tidak. Menyetelnya ke terbalik akan memutar animasi maju lalu mundur berulang kali, hingga jumlah pengulangan tercapai.
- Kumpulan animator: Anda dapat mengelompokkan animasi ke dalam kumpulan logis yang diputar bersamaan, secara berurutan, atau setelah penundaan yang ditentukan.
- Penundaan refresh frame: Anda dapat menentukan frekuensi refresh frame animasi. Setelan defaultnya adalah refresh setiap 10 milidetik, tetapi kecepatan refresh frame aplikasi pada akhirnya bergantung pada kesibukan sistem secara keseluruhan dan seberapa cepat sistem dapat melayani timer yang mendasarinya.
Untuk melihat contoh lengkap animasi properti, lihat class ChangeColor
dalam contoh CustomTransition di GitHub.
Cara kerja animasi properti
Pertama-tama, mari kita bahas cara kerja animasi melalui sebuah contoh sederhana. Gambar 1 menggambarkan
objek hipotesis yang dianimasikan dengan properti x
, yang merepresentasikan
lokasi horizontalnya di layar. Durasi animasi disetel ke 40 milidetik dengan jarak tempuh 40 piksel. Setiap 10 milidetik, yang merupakan kecepatan refresh frame default, objek bergerak secara horizontal sejauh 10 piksel. Pada akhir 40 md, animasi akan berhenti, dan objek berakhir pada
posisi horizontal 40. Ini adalah contoh animasi dengan interpolasi linier, yang berarti
objek bergerak dengan kecepatan konstan.
Anda juga dapat menentukan animasi untuk memiliki interpolasi non-linear. Gambar 2 mengilustrasikan objek hipotesis yang melaju cepat di awal animasi, dan melambat di akhir animasi. Objek masih bergerak 40 piksel dalam 40 milidetik, tetapi tidak linier. Di awal, animasi ini dipercepat hingga titik tengah, lalu melambat dari titik tengah hingga akhir animasi. Seperti ditunjukkan oleh Gambar 2, jarak yang ditempuh di awal dan akhir animasi kurang dari di tengah.
Mari kita lihat secara mendetail bagaimana komponen penting dari sistem animasi properti akan menghitung animasi seperti dalam ilustrasi di atas. Gambar 3 menunjukkan cara class utama bekerja satu sama lain.
Objek ValueAnimator
melacak pengaturan waktu animasi, seperti berapa lama animasi telah berjalan, dan nilai saat ini dari properti yang dianimasikannya.
ValueAnimator
mengenkapsulasi TimeInterpolator
, yang menentukan interpolasi animasi, dan TypeEvaluator
, yang menentukan cara menghitung nilai untuk properti yang sedang dianimasikan. Misalnya, dalam Gambar 2, TimeInterpolator
yang digunakan adalah AccelerateDecelerateInterpolator
dan TypeEvaluator
adalah IntEvaluator
.
Untuk memulai animasi, buat ValueAnimator
dan berikan nilai awal dan akhir untuk properti yang ingin Anda animasikan, beserta durasi animasinya. Saat Anda memanggil start()
, animasi akan
dimulai. Selama seluruh animasi, ValueAnimator
akan menghitung fraksi berlalu antara 0 dan 1, berdasarkan durasi animasi dan berapa banyak waktu yang telah berlalu. Fraksi berlalu menunjukkan persentase waktu yang telah diselesaikan animasi, 0 yang berarti 0% dan 1 berarti 100%. Misalnya, pada Gambar 1, fraksi berlalu pada t = 10 md adalah 0,25 karena total durasinya adalah t = 40 md.
Setelah selesai menghitung fraksi berlalu, ValueAnimator
akan memanggil TimeInterpolator
yang saat ini ditetapkan, untuk menghitung fraksi terinterpolasi. Fraksi terinterpolasi memetakan fraksi berlalu ke fraksi baru yang memperhitungkan interpolasi waktu yang ditetapkan. Misalnya, pada Gambar 2, karena animasi dipercepat secara perlahan, fraksi terinterpolasi, sekitar 0,15, lebih kecil daripada
fraksi berlalu, 0,25, pada t = 10 md. Dalam Gambar 1, fraksi terinterpolasi selalu sama dengan
fraksi berlalu.
Saat fraksi terinterpolasi dihitung, ValueAnimator
akan memanggil TypeEvaluator
yang sesuai, untuk menghitung nilai properti yang Anda animasikan, berdasarkan fraksi interpolasi, nilai awal, dan nilai akhir animasi. Misalnya, dalam Gambar 2, fraksi terinterpolasi adalah 0,15 pada t =
10 md, sehingga nilai untuk properti pada saat itu adalah 0,15 × (40 - 0), atau 6.
Perbedaan antara animasi properti dengan animasi tampilan
Sistem animasi tampilan menyediakan kemampuan untuk hanya menganimasikan objek View
, sehingga jika ingin menganimasikan objek non-View
, Anda harus mengimplementasikan
kode sendiri untuk melakukannya. Sistem animasi tampilan juga dibatasi karena hanya
mengekspos beberapa aspek objek View
untuk dianimasikan, seperti penskalaan dan
rotasi Tampilan, tetapi bukan warna latar belakang.
Kekurangan lain dari sistem animasi tampilan adalah sistem ini hanya mengubah tempat View digambar, bukan View itu sendiri. Misalnya, jika Anda menganimasikan tombol untuk bergerak ke seluruh layar, tombol akan menggambar dengan benar, tetapi lokasi sebenarnya tempat Anda dapat mengklik tombol tidak berubah, sehingga Anda harus menerapkan logika Anda sendiri untuk menangani hal ini.
Dengan sistem animasi properti, batasan ini sepenuhnya dihapus, dan Anda dapat menganimasikan properti apa pun dari objek apa pun (View dan non-View) dan objek itu sendiri benar-benar diubah. Sistem animasi properti juga lebih tangguh dalam menangani animasi. Pada level tinggi, Anda menetapkan animator ke properti yang ingin dianimasikan, seperti warna, posisi, atau ukuran, dan dapat menentukan aspek animasi seperti interpolasi dan sinkronisasi beberapa animator.
Namun, sistem animasi tampilan memerlukan lebih sedikit waktu untuk disiapkan dan lebih sedikit kode untuk ditulis. Jika animasi tampilan sudah menyelesaikan semua hal yang perlu Anda lakukan, atau jika kode yang ada sudah berfungsi sesuai keinginan, Anda tidak perlu menggunakan sistem animasi properti. Mungkin juga masuk akal untuk menggunakan kedua sistem animasi tersebut untuk situasi yang berbeda jika muncul kasus penggunaan.
Ringkasan API
Anda dapat menemukan sebagian besar API sistem animasi properti di android.animation
. Karena sistem animasi tampilan sudah menentukan banyak interpolator di android.view.animation
, Anda juga dapat menggunakan interpolator tersebut dalam sistem animasi properti. Tabel berikut menjelaskan komponen utama dari sistem animasi properti.
Class Animator
menyediakan struktur dasar untuk membuat animasi. Biasanya, Anda tidak menggunakan class ini secara langsung karena class tersebut hanya menyediakan fungsi minimal yang harus diperluas untuk sepenuhnya mendukung nilai animasi. Subclass berikut memperluas Animator
:
Class | Deskripsi |
---|---|
ValueAnimator |
Mesin pengaturan waktu utama untuk animasi properti yang juga menghitung nilai untuk properti yang akan dianimasikan. Elemen ini memiliki semua fungsi inti yang menghitung nilai animasi dan berisi detail pengaturan waktu setiap animasi, informasi tentang apakah animasi akan berulang, pemroses yang menerima peristiwa update, dan kemampuan untuk menetapkan jenis kustom yang akan dievaluasi. Ada dua bagian dalam properti animasi: menghitung nilai animasi dan menetapkan nilai tersebut pada objek dan properti yang sedang dianimasikan. ValueAnimator tidak menjalankan bagian kedua, sehingga Anda harus memproses
pembaruan nilai yang dihitung oleh ValueAnimator dan
mengubah objek yang ingin dianimasikan dengan logika Anda sendiri. Lihat bagian Menganimasikan dengan ValueAnimator untuk informasi selengkapnya. |
ObjectAnimator |
Subclass ValueAnimator yang memungkinkan Anda menetapkan objek target dan properti objek yang akan dianimasikan. Class ini memperbarui properti yang sesuai saat menghitung nilai baru untuk animasi tersebut. Anda akan sering menggunakan ObjectAnimator , karena cara ini membuat proses penganimasian nilai pada objek target jauh lebih mudah. Namun,
terkadang Anda perlu menggunakan ValueAnimator secara langsung karena ObjectAnimator memiliki beberapa batasan lainnya, misalnya mengharuskan
metode pengakses tertentu ada pada objek target. |
AnimatorSet |
Menyediakan mekanisme untuk mengelompokkan animasi bersama-sama sehingga berjalan terkait satu sama lain. Anda dapat mengatur animasi untuk diputar secara bersamaan, berurutan, atau setelah penundaan tertentu. Lihat bagian Mengatur koreografi beberapa animasi dengan Animator Set untuk mengetahui informasi selengkapnya. |
Evaluator memberi tahu sistem animasi properti cara menghitung nilai untuk properti tertentu. Penghitung waktu mengambil data pengaturan waktu yang disediakan oleh class Animator
, nilai awal dan akhir animasi, serta menghitung nilai animasi properti berdasarkan data ini. Sistem animasi properti menyediakan evaluator berikut:
Class/Antarmuka | Deskripsi |
---|---|
IntEvaluator |
Evaluator default untuk menghitung nilai properti int . |
FloatEvaluator |
Evaluator default untuk menghitung nilai properti float . |
ArgbEvaluator |
Evaluator default untuk menghitung nilai properti warna yang direpresentasikan sebagai nilai heksadesimal. |
TypeEvaluator |
Antarmuka yang memungkinkan Anda membuat evaluator sendiri. Jika menganimasikan properti objek yang bukan int , float , atau warna, Anda harus mengimplementasikan antarmuka TypeEvaluator untuk menentukan cara menghitung nilai teranimasi properti objek. Anda juga dapat menentukan TypeEvaluator kustom untuk nilai int , float , dan
warna, jika ingin memproses jenis tersebut secara berbeda dengan perilaku default.
Lihat bagian Menggunakan TypeEvaluator untuk mengetahui informasi selengkapnya tentang cara menulis evaluator kustom. |
Interpolator waktu menentukan cara menghitung nilai tertentu dalam animasi sebagai
fungsi dari waktu. Misalnya, Anda dapat menentukan animasi agar terjadi secara linier di seluruh animasi, yang berarti animasi bergerak secara merata sepanjang waktu, atau Anda dapat menentukan animasi untuk menggunakan waktu non-linear, misalnya, berakselerasi di awal dan melambat di akhir animasi. Tabel 3 menjelaskan interpolator yang terdapat dalam android.view.animation
. Jika interpolator yang disediakan tidak ada yang sesuai dengan kebutuhan Anda, terapkan antarmuka TimeInterpolator
dan buat interpolator Anda sendiri. Lihat Menggunakan interpolator untuk informasi selengkapnya tentang cara menulis interpolator
kustom.
Class/Antarmuka | Deskripsi |
---|---|
AccelerateDecelerateInterpolator |
Interpolator yang laju perubahannya dimulai dan diakhiri dengan lambat, tetapi dipercepat di tengahnya. |
AccelerateInterpolator |
Interpolator yang laju perubahannya dimulai dengan lambat, lalu dipercepat. |
AnticipateInterpolator |
Interpolator yang perubahannya dimulai secara mundur, lalu melejit maju. |
AnticipateOvershootInterpolator |
Interpolator yang perubahannya dimulai secara mundur, melejit maju, dan melampaui nilai target, lalu akhirnya kembali ke nilai akhir. |
BounceInterpolator |
Interpolator yang perubahannya memantul di bagian akhir. |
CycleInterpolator |
Interpolator yang animasinya berulang selama sejumlah siklus tertentu. |
DecelerateInterpolator |
Interpolator yang laju perubahannya dimulai dengan cepat, lalu melambat. |
LinearInterpolator |
Interpolator yang laju perubahannya konstan. |
OvershootInterpolator |
Interpolator yang perubahannya melejit maju dan melampaui nilai terakhir lalu kembali. |
TimeInterpolator |
Antarmuka yang memungkinkan Anda menerapkan interpolator sendiri. |
Menganimasikan dengan ValueAnimator
Class ValueAnimator
memungkinkan Anda menganimasikan nilai beberapa jenis selama
durasi animasi dengan menentukan kumpulan int
, float
, atau nilai
warna yang akan dianimasikan. Anda mendapatkan ValueAnimator
dengan memanggil salah satu
metode factory-nya: ofInt()
, ofFloat()
, atau ofObject()
. Contoh:
Kotlin
ValueAnimator.ofFloat(0f, 100f).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f); animation.setDuration(1000); animation.start();
Dalam kode ini, ValueAnimator
mulai menghitung nilai animasi, antara 0 dan 100, selama 1.000 milidetik, saat metode start()
berjalan.
Anda juga dapat menentukan jenis kustom yang akan dianimasikan dengan melakukan langkah berikut:
Kotlin
ValueAnimator.ofObject(MyTypeEvaluator(), startPropertyValue, endPropertyValue).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue); animation.setDuration(1000); animation.start();
Dalam kode ini, ValueAnimator
mulai menghitung nilai animasi, antara startPropertyValue
dan endPropertyValue
menggunakan logika yang disediakan oleh MyTypeEvaluator
selama 1.000 milidetik, saat metode start()
berjalan.
Anda dapat menggunakan nilai animasi dengan menambahkan
AnimatorUpdateListener
ke objek ValueAnimator
, seperti yang ditunjukkan dalam
kode berikut:
Kotlin
ValueAnimator.ofObject(...).apply { ... addUpdateListener { updatedAnimation -> // You can use the animated value in a property that uses the // same type as the animation. In this case, you can use the // float value in the translationX property. textView.translationX = updatedAnimation.animatedValue as Float } ... }
Java
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator updatedAnimation) { // You can use the animated value in a property that uses the // same type as the animation. In this case, you can use the // float value in the translationX property. float animatedValue = (float)updatedAnimation.getAnimatedValue(); textView.setTranslationX(animatedValue); } });
Dalam metode onAnimationUpdate()
, Anda dapat mengakses nilai animasi yang diperbarui dan menggunakannya dalam properti salah satu tampilan Anda. Untuk mengetahui informasi selengkapnya tentang pemroses, lihat bagian Pemroses animasi.
Menganimasikan dengan ObjectAnimator
ObjectAnimator
adalah subclass dari ValueAnimator
(dibahas di bagian sebelumnya) dan menggabungkan mesin pengaturan waktu dan komputasi nilai ValueAnimator
dengan kemampuan untuk menganimasikan properti bernama dari sebuah objek target. Hal ini mempermudah penganimasian objek apa pun, karena Anda tidak perlu lagi menerapkan ValueAnimator.AnimatorUpdateListener
, karena properti yang dianimasikan diperbarui secara otomatis.
Membuat instance ObjectAnimator
mirip dengan ValueAnimator
, tetapi Anda juga menentukan objek dan nama properti objek tersebut (sebagai
String) bersama dengan nilai yang akan dianimasikan di antaranya:
Kotlin
ObjectAnimator.ofFloat(textView, "translationX", 100f).apply { duration = 1000 start() }
Java
ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f); animation.setDuration(1000); animation.start();
Agar ObjectAnimator
memperbarui properti dengan benar, Anda harus melakukan hal-hal berikut:
- Properti objek yang Anda animasikan harus memiliki fungsi penyetel (dalam camel case) dalam bentuk
set<PropertyName>()
. KarenaObjectAnimator
otomatis memperbarui properti selama animasi, properti harus dapat mengakses properti dengan metode penyetel ini. Misalnya, jika nama properti adalahfoo
, Anda harus memiliki metodesetFoo()
. Jika metode penyetel ini tidak ada, Anda memiliki tiga opsi:- Menambahkan metode setter ke class jika Anda memiliki hak untuk melakukannya.
- Gunakan class wrapper yang dapat Anda ubah dan minta wrapper tersebut menerima nilai dengan metode penyetel yang valid, lalu meneruskannya ke objek asli.
- Sebagai gantinya, gunakan
ValueAnimator
.
- Jika Anda hanya menentukan satu nilai untuk parameter
values...
di salah satu metode factoryObjectAnimator
, hal tersebut diasumsikan sebagai nilai akhir animasi. Oleh karena itu, properti objek yang Anda animasikan harus memiliki fungsi pengambil yang digunakan untuk mendapatkan nilai awal animasi. Fungsi pengambil harus dalam bentukget<PropertyName>()
. Misalnya, jika nama properti adalahfoo
, Anda harus memiliki metodegetFoo()
. - Metode pengambil (jika diperlukan) dan penyetel dari properti yang Anda animasikan harus
beroperasi pada jenis yang sama dengan nilai awal dan akhir yang Anda tentukan untuk
ObjectAnimator
. Misalnya, Anda harus memilikitargetObject.setPropName(float)
dantargetObject.getPropName()
jika Anda membuatObjectAnimator
berikut:ObjectAnimator.ofFloat(targetObject, "propName", 1f)
- Bergantung pada properti atau objek yang dianimasikan, Anda mungkin perlu memanggil metode
invalidate()
di View untuk memaksa layar menggambar ulang dirinya sendiri dengan nilai animasi yang diperbarui. Anda melakukannya di callbackonAnimationUpdate()
. Misalnya, menganimasikan properti warna sebuah objek Drawable hanya akan menyebabkan perubahan pada layar jika objek tersebut menggambar ulang dirinya sendiri. Semua penyetel properti di View, sepertisetAlpha()
dansetTranslationX()
membatalkan View dengan benar, sehingga Anda tidak perlu membatalkan View saat memanggil metode ini dengan nilai baru. Untuk mengetahui informasi selengkapnya tentang pemroses, lihat bagian Pemroses animasi.
Mengatur koreografi beberapa animasi dengan AnimatorSet
Dalam banyak kasus, Anda ingin memutar animasi yang bergantung pada kapan animasi lain dimulai atau
selesai. Sistem Android memungkinkan Anda memaketkan animasi bersama-sama menjadi AnimatorSet
, sehingga Anda dapat menentukan apakah akan memulai animasi
secara bersamaan, berurutan, atau setelah penundaan yang ditentukan. Anda juga dapat menempatkan objek AnimatorSet
di dalam objek AnimatorSet lainnya.
Cuplikan kode berikut memutar objek Animator
berikut dengan cara berikut:
- Memutar
bounceAnim
. - Memutar
squashAnim1
,squashAnim2
,stretchAnim1
, danstretchAnim2
secara bersamaan. - Memutar
bounceBackAnim
. - Memutar
fadeAnim
.
Kotlin
val bouncer = AnimatorSet().apply { play(bounceAnim).before(squashAnim1) play(squashAnim1).with(squashAnim2) play(squashAnim1).with(stretchAnim1) play(squashAnim1).with(stretchAnim2) play(bounceBackAnim).after(stretchAnim2) } val fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply { duration = 250 } AnimatorSet().apply { play(bouncer).before(fadeAnim) start() }
Java
AnimatorSet bouncer = new AnimatorSet(); bouncer.play(bounceAnim).before(squashAnim1); bouncer.play(squashAnim1).with(squashAnim2); bouncer.play(squashAnim1).with(stretchAnim1); bouncer.play(squashAnim1).with(stretchAnim2); bouncer.play(bounceBackAnim).after(stretchAnim2); ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(bouncer).before(fadeAnim); animatorSet.start();
Pemroses animasi
Anda bisa memproses peristiwa penting selama durasi animasi dengan pemroses yang dijelaskan di bawah ini.
Animator.AnimatorListener
onAnimationStart()
- Dipanggil saat animasi dimulai.onAnimationEnd()
- Dipanggil saat animasi berakhir.onAnimationRepeat()
- Dipanggil saat animasi berulang dengan sendirinya.onAnimationCancel()
- Dipanggil saat animasi dibatalkan. Animasi yang dibatalkan juga memanggilonAnimationEnd()
, terlepas dari bagaimana animasi tersebut diakhiri.
ValueAnimator.AnimatorUpdateListener
-
onAnimationUpdate()
- dipanggil di setiap frame animasi. Proses peristiwa ini untuk menggunakan nilai terhitung yang dihasilkan olehValueAnimator
selama animasi. Untuk menggunakan nilai ini, buat kueri objekValueAnimator
yang diteruskan ke peristiwa untuk mendapatkan nilai animasi saat ini dengan metodegetAnimatedValue()
. Penerapan pemroses ini diperlukan jika Anda menggunakanValueAnimator
.Bergantung pada properti atau objek yang dianimasikan, Anda mungkin perlu memanggil
invalidate()
pada View untuk memaksa area layar tersebut menggambar ulang dirinya sendiri dengan nilai animasi baru. Misalnya, menganimasikan properti warna sebuah objek Drawable hanya akan menimbulkan pembaruan pada layar jika objek tersebut menggambar ulang dirinya sendiri. Semua penyetel properti di View, sepertisetAlpha()
dansetTranslationX()
membatalkan View dengan benar, sehingga Anda tidak perlu membatalkan View saat memanggil metode ini dengan nilai baru.
-
Anda dapat memperluas class AnimatorListenerAdapter
, bukan
mengimplementasikan antarmuka Animator.AnimatorListener
, jika tidak
ingin mengimplementasikan semua metode antarmuka
Animator.AnimatorListener
. Class AnimatorListenerAdapter
menyediakan implementasi
kosong dari metode yang dapat Anda pilih untuk diganti.
Misalnya, cuplikan kode berikut membuat AnimatorListenerAdapter
hanya untuk callback onAnimationEnd()
:
Kotlin
ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply { duration = 250 addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { balls.remove((animation as ObjectAnimator).target) } }) }
Java
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); fadeAnim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { balls.remove(((ObjectAnimator)animation).getTarget()); }
Menganimasikan perubahan tata letak pada objek ViewGroup
Sistem animasi properti memberikan kemampuan untuk menganimasikan perubahan pada objek ViewGroup serta memberikan cara mudah untuk menganimasikan objek View itu sendiri.
Anda dapat menganimasikan perubahan tata letak dalam ViewGroup dengan class LayoutTransition
. Tampilan di dalam ViewGroup dapat
melalui animasi yang muncul dan menghilang saat Anda menambahkannya ke atau
menghapusnya dari ViewGroup atau saat Anda memanggil metode
setVisibility()
View dengan
VISIBLE
, INVISIBLE
, atau
GONE
. View yang tersisa di ViewGroup juga dapat
dianimasikan ke posisi barunya saat Anda menambahkan atau menghapus View. Anda dapat menentukan
animasi berikut dalam objek LayoutTransition
dengan memanggil setAnimator()
dan meneruskan objek Animator
dengan salah satu
konstanta LayoutTransition
berikut:
APPEARING
- Flag yang menunjukkan animasi yang berjalan pada item yang muncul di container.CHANGE_APPEARING
- Flag yang menunjukkan animasi yang berjalan pada item yang berubah karena adanya item baru yang muncul di container.DISAPPEARING
- Flag yang menunjukkan animasi yang berjalan pada item yang menghilang dari container.CHANGE_DISAPPEARING
- Flag yang menunjukkan animasi yang berjalan pada item yang berubah karena item menghilang dari container.
Anda dapat menentukan animasi kustom sendiri untuk keempat jenis peristiwa ini guna menyesuaikan tampilan transisi tata letak atau cukup memberi tahu sistem animasi untuk menggunakan animasi default.
Untuk menetapkan atribut android:animateLayoutchanges
ke true
bagi ViewGroup, lakukan hal berikut:
<LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/verticalContainer" android:animateLayoutChanges="true" />
Menetapkan atribut ini ke true (benar) akan otomatis menganimasikan View yang ditambahkan atau dihapus dari ViewGroup serta View lainnya di ViewGroup.
Menganimasikan perubahan status tampilan menggunakan StateListAnimator
Class StateListAnimator
memungkinkan Anda menentukan animator yang berjalan saat
status tampilan berubah. Objek ini berperilaku sebagai wrapper untuk
objek Animator
, yang memanggil animasi tersebut setiap kali status tampilan
yang ditentukan (seperti "ditekan" atau "difokus") berubah.
StateListAnimator
dapat ditentukan dalam resource XML dengan elemen
<selector>
root dan elemen <item>
turunan yang masing-masing menentukan
status tampilan berbeda yang ditentukan oleh class StateListAnimator
. Setiap
<item>
berisi definisi untuk set animasi properti.
Misalnya, file berikut membuat animator daftar status yang mengubah skala x dan y tampilan saat ditekan:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- the pressed state; increase x and y size to 150% --> <item android:state_pressed="true"> <set> <objectAnimator android:propertyName="scaleX" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1.5" android:valueType="floatType"/> <objectAnimator android:propertyName="scaleY" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1.5" android:valueType="floatType"/> </set> </item> <!-- the default, non-pressed state; set x and y size to 100% --> <item android:state_pressed="false"> <set> <objectAnimator android:propertyName="scaleX" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1" android:valueType="floatType"/> <objectAnimator android:propertyName="scaleY" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1" android:valueType="floatType"/> </set> </item> </selector>
Untuk melampirkan animator daftar status ke tampilan, tambahkan atribut
android:stateListAnimator
sebagai berikut:
<Button android:stateListAnimator="@xml/animate_scale" ... />
Sekarang animasi yang ditentukan dalam animate_scale.xml
digunakan saat status
tombol ini berubah.
Atau, untuk menetapkan animator daftar status ke tampilan dalam kode Anda, gunakan
metode AnimatorInflater.loadStateListAnimator()
, dan tetapkan animator ke
tampilan Anda dengan metode View.setStateListAnimator()
.
Atau, alih-alih menganimasikan properti tampilan, Anda dapat memutar animasi drawable di antara
perubahan status, menggunakan AnimatedStateListDrawable
.
Beberapa widget sistem di Android 5.0 menggunakan animasi ini secara default. Contoh berikut menunjukkan cara
menentukan AnimatedStateListDrawable
sebagai resource XML:
<!-- res/drawable/myanimstatedrawable.xml --> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- provide a different drawable for each state--> <item android:id="@+id/pressed" android:drawable="@drawable/drawableP" android:state_pressed="true"/> <item android:id="@+id/focused" android:drawable="@drawable/drawableF" android:state_focused="true"/> <item android:id="@id/default" android:drawable="@drawable/drawableD"/> <!-- specify a transition --> <transition android:fromId="@+id/default" android:toId="@+id/pressed"> <animation-list> <item android:duration="15" android:drawable="@drawable/dt1"/> <item android:duration="15" android:drawable="@drawable/dt2"/> ... </animation-list> </transition> ... </animated-selector>
Menggunakan TypeEvaluator
Jika ingin menganimasikan jenis yang tidak dikenal oleh sistem Android, Anda dapat membuat evaluator sendiri dengan menerapkan antarmuka TypeEvaluator
. Jenis yang
diketahui oleh sistem Android adalah int
, float
, atau warna, yang
didukung oleh evaluator jenis
IntEvaluator
, FloatEvaluator
, dan ArgbEvaluator
.
Hanya ada satu metode yang dapat diterapkan dalam antarmuka TypeEvaluator
, yaitu metode evaluate()
. Hal ini memungkinkan animator yang Anda gunakan untuk menampilkan nilai yang sesuai untuk properti animasi Anda pada titik animasi saat ini. Class FloatEvaluator
menunjukkan
cara melakukannya:
Kotlin
private class FloatEvaluator : TypeEvaluator<Any> { override fun evaluate(fraction: Float, startValue: Any, endValue: Any): Any { return (startValue as Number).toFloat().let { startFloat -> startFloat + fraction * ((endValue as Number).toFloat() - startFloat) } } }
Java
public class FloatEvaluator implements TypeEvaluator { public Object evaluate(float fraction, Object startValue, Object endValue) { float startFloat = ((Number) startValue).floatValue(); return startFloat + fraction * (((Number) endValue).floatValue() - startFloat); } }
Catatan: Saat berjalan, ValueAnimator
(atau ObjectAnimator
) akan menghitung fraksi berlalu saat ini dari animasi (nilai antara 0 dan 1), lalu menghitung versi terinterpolasi dari animasi tersebut, bergantung pada interpolator yang Anda gunakan. Fraksi terinterpolasi adalah nilai yang diterima TypeEvaluator
melalui parameter fraction
sehingga Anda tidak perlu memperhitungkan interpolator saat menghitung nilai animasi.
Menggunakan Interpolator
Interpolator menentukan cara menghitung nilai tertentu dalam animasi sebagai fungsi dari waktu. Misalnya, Anda dapat menentukan animasi agar terjadi secara linier di seluruh animasi, yang berarti animasi bergerak secara merata sepanjang waktu, atau Anda dapat menentukan animasi untuk menggunakan waktu non-linear, misalnya, menggunakan akselerasi atau deselerasi di awal atau akhir animasi.
Interpolator dalam sistem animasi menerima sebuah fraksi dari Animator yang mewakili waktu yang telah berlalu dari animasi tersebut. Interpolator mengubah fraksi ini agar bertepatan dengan jenis animasi yang ingin disediakannya. Sistem Android menyediakan sekumpulan interpolator yang umum dalam
android.view.animation package
. Jika tidak ada satu pun dari keduanya yang sesuai dengan
kebutuhan, Anda dapat menerapkan antarmuka TimeInterpolator
dan membuatnya
sendiri.
Sebagai contoh, cara interpolator default AccelerateDecelerateInterpolator
dan LinearInterpolator
menghitung fraksi terinterpolasi dibandingkan di bawah ini.
LinearInterpolator
tidak berpengaruh pada fraksi berlalu. AccelerateDecelerateInterpolator
melaju cepat di awal animasi dan melambat di akhir animasi. Metode berikut menentukan logika untuk interpolator ini:
AccelerateDecelerateInterpolator
Kotlin
override fun getInterpolation(input: Float): Float = (Math.cos((input + 1) * Math.PI) / 2.0f).toFloat() + 0.5f
Java
@Override public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; }
LinearInterpolator
Kotlin
override fun getInterpolation(input: Float): Float = input
Java
@Override public float getInterpolation(float input) { return input; }
Tabel berikut menunjukkan nilai perkiraan yang dihitung oleh interpolator ini untuk animasi yang berlangsung selama 1.000 md:
mdtk berlalu | Fraksi berlalu/Fraksi terinterpolasi (Linear) | Fraksi terinterpolasi (Akselerasi/Deselerasi) |
---|---|---|
0 | 0 | 0 |
200 | 0,2 | 0,1 |
400 | 0,4 | 0,345 |
600 | .6 | 0,8 |
800 | 0,8 | 0,9 |
1.000 | 1 | 1 |
Seperti yang ditampilkan dalam tabel, LinearInterpolator
mengubah nilai
dengan kecepatan yang sama, 0,2 untuk setiap 200 md yang berlalu. AccelerateDecelerateInterpolator
mengubah nilai ini lebih cepat daripada LinearInterpolator
antara 200 md dan 600 md, dan lebih lambat antara 600 md dan
1.000 md.
Menentukan keyframe
Objek Keyframe
terdiri dari pasangan waktu/nilai yang memungkinkan Anda menentukan status tertentu pada waktu tertentu dari sebuah animasi. Setiap keyframe juga dapat memiliki
interpolatornya sendiri untuk mengontrol perilaku animasi dalam interval antara waktu
keyframe sebelumnya dan waktu keyframe ini.
Untuk membuat instance objek Keyframe
, Anda harus menggunakan salah satu metode factory, yaitu ofInt()
, ofFloat()
, atau ofObject()
untuk mendapatkan jenis Keyframe
yang sesuai. Lalu panggil
metode factory ofKeyframe()
untuk
mendapatkan objek PropertyValuesHolder
. Setelah memiliki objek ini, Anda bisa mendapatkan animator dengan meneruskan objek PropertyValuesHolder
dan objek yang akan dianimasikan. Cuplikan kode berikut menunjukkan cara melakukannya:
Kotlin
val kf0 = Keyframe.ofFloat(0f, 0f) val kf1 = Keyframe.ofFloat(.5f, 360f) val kf2 = Keyframe.ofFloat(1f, 0f) val pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2) ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation).apply { duration = 5000 }
Java
Keyframe kf0 = Keyframe.ofFloat(0f, 0f); Keyframe kf1 = Keyframe.ofFloat(.5f, 360f); Keyframe kf2 = Keyframe.ofFloat(1f, 0f); PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2); ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation); rotationAnim.setDuration(5000);
Menganimasikan tampilan
Sistem animasi properti memungkinkan animasi objek View yang disederhanakan dan menawarkan beberapa keunggulan dibandingkan sistem animasi tampilan. Sistem animasi tampilan mengubah objek View dengan mengubah cara objek tersebut digambar. Hal ini ditangani di penampung setiap View, karena View itu sendiri tidak memiliki properti untuk dimanipulasi. Hasilnya, View dianimasikan, tetapi objek View itu sendiri tidak berubah. Hal ini menyebabkan perilaku seperti objek yang masih ada di lokasi aslinya, meskipun objek tersebut digambar pada lokasi yang berbeda di layar. Di Android 3.0, properti baru serta metode pengambil dan penyetel terkait ditambahkan untuk menghilangkan kekurangan ini.
Sistem animasi properti dapat menganimasikan View di layar dengan mengubah properti sebenarnya dalam objek View. Selain
itu, View juga otomatis memanggil metode invalidate()
untuk memuat ulang layar setiap kali propertinya diubah. Properti baru di class View
yang memfasilitasi animasi properti adalah:
translationX
dantranslationY
: Properti ini mengontrol lokasi View sebagai delta dari koordinat kiri dan atasnya, yang ditetapkan oleh penampung tata letaknya.rotation
,rotationX
, danrotationY
: Properti ini mengontrol rotasi dalam 2D (propertirotation
) dan 3D di sekitar titik pivot.scaleX
danscaleY
: Properti ini mengontrol penskalaan 2D View di sekitar titik pivotnya.pivotX
danpivotY
: Properti ini mengontrol lokasi titik pivot, yang memungkinkan terjadinya rotasi dan transformasi penskalaan. Secara default, titik pivot terletak di tengah objek.x
dany
: Ini adalah properti utilitas sederhana untuk mendeskripsikan lokasi akhir View dalam container-nya, sebagai jumlah dari nilai kiri dan atas serta nilai TranslationX dan TranslationY.alpha
: Menunjukkan transparansi alfa pada View. Nilai ini secara default adalah 1 (buram), dengan nilai 0 menunjukkan transparansi penuh (tidak terlihat).
Untuk menganimasikan properti objek View, seperti warna atau nilai rotasinya, Anda hanya perlu membuat animator properti dan menentukan properti View yang ingin Anda animasikan. Contoh:
Kotlin
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f)
Java
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
Untuk mengetahui informasi selengkapnya tentang cara membuat animator, lihat bagian tentang menganimasikan dengan ValueAnimator dan ObjectAnimator.
Menganimasikan dengan ViewPropertyAnimator
ViewPropertyAnimator
menyediakan cara sederhana untuk menganimasikan beberapa
properti View
secara paralel, menggunakan satu objek Animator
dasar. Perilakunya sangat mirip dengan ObjectAnimator
, karena memodifikasi
nilai sebenarnya dari properti tampilan, tetapi lebih efisien saat menganimasikan banyak properti
sekaligus. Selain itu, kode untuk menggunakan ViewPropertyAnimator
jauh
lebih ringkas dan lebih mudah dibaca. Cuplikan kode berikut menunjukkan perbedaan dalam penggunaan beberapa
objek ObjectAnimator
, ObjectAnimator
tunggal, dan ViewPropertyAnimator
saat
menganimasikan properti x
dan y
tampilan secara bersamaan.
Beberapa ObjectAnimator
Kotlin
val animX = ObjectAnimator.ofFloat(myView, "x", 50f) val animY = ObjectAnimator.ofFloat(myView, "y", 100f) AnimatorSet().apply { playTogether(animX, animY) start() }
Java
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f); ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f); AnimatorSet animSetXY = new AnimatorSet(); animSetXY.playTogether(animX, animY); animSetXY.start();
Satu ObjectAnimator
Kotlin
val pvhX = PropertyValuesHolder.ofFloat("x", 50f) val pvhY = PropertyValuesHolder.ofFloat("y", 100f) ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start()
Java
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f); ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start();
ViewPropertyAnimator
Kotlin
myView.animate().x(50f).y(100f)
Java
myView.animate().x(50f).y(100f);
Untuk mengetahui informasi selengkapnya tentang ViewPropertyAnimator
, lihat postingan blog
Developer Android yang sesuai.
Mendeklarasikan animasi dalam XML
Sistem animasi properti memungkinkan Anda mendeklarasikan animasi properti dengan XML, bukan melakukannya secara terprogram. Dengan menentukan animasi dalam XML, Anda dapat menggunakan kembali animasi dalam beberapa aktivitas dengan mudah dan mengedit urutan animasi dengan lebih mudah.
Untuk membedakan file animasi yang menggunakan API animasi properti baru dengan yang menggunakan
framework animasi tampilan versi lama,
mulai dari Android 3.1, Anda harus menyimpan file XML untuk animasi properti di direktori res/animator/
.
Class animasi properti berikut memiliki dukungan deklarasi XML dengan tag XML berikut:
ValueAnimator
-<animator>
ObjectAnimator
-<objectAnimator>
AnimatorSet
-<set>
Untuk menemukan atribut yang dapat Anda gunakan dalam deklarasi XML, lihat Resource animasi. Contoh berikut memutar dua set animasi objek secara berurutan, dengan set bertingkat pertama memutar dua animasi objek secara bersamaan:
<set android:ordering="sequentially"> <set> <objectAnimator android:propertyName="x" android:duration="500" android:valueTo="400" android:valueType="intType"/> <objectAnimator android:propertyName="y" android:duration="500" android:valueTo="300" android:valueType="intType"/> </set> <objectAnimator android:propertyName="alpha" android:duration="500" android:valueTo="1f"/> </set>
Untuk menjalankan animasi ini, Anda harus meng-inflate resource XML dalam kode Anda ke objek AnimatorSet
, lalu menetapkan objek target untuk semua animasi
sebelum memulai set animasi tersebut. Demi kepraktisan, panggilan ke setTarget()
akan menetapkan satu objek target untuk semua turunan AnimatorSet
. Kode berikut menunjukkan cara melakukannya:
Kotlin
(AnimatorInflater.loadAnimator(myContext, R.animator.property_animator) as AnimatorSet).apply { setTarget(myObject) start() }
Java
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.animator.property_animator); set.setTarget(myObject); set.start();
Anda juga dapat mendeklarasikan ValueAnimator
dalam XML, seperti
yang ditunjukkan pada contoh berikut:
<animator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:valueType="floatType" android:valueFrom="0f" android:valueTo="-100f" />
Untuk menggunakan ValueAnimator
sebelumnya dalam kode, Anda
harus meng-inflate objek, menambahkan
AnimatorUpdateListener
,
mendapatkan nilai animasi yang diperbarui, dan menggunakannya dalam properti salah satu tampilan Anda,
seperti yang ditunjukkan pada kode berikut:
Kotlin
(AnimatorInflater.loadAnimator(this, R.animator.animator) as ValueAnimator).apply { addUpdateListener { updatedAnimation -> textView.translationX = updatedAnimation.animatedValue as Float } start() }
Java
ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator); xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator updatedAnimation) { float animatedValue = (float)updatedAnimation.getAnimatedValue(); textView.setTranslationX(animatedValue); } }); xmlAnimator.start();
Untuk mengetahui informasi tentang sintaksis XML untuk menentukan animasi properti, lihat Resource animasi .
Efek potensial pada performa UI
Animator yang mengupdate UI menyebabkan pekerjaan rendering tambahan untuk setiap frame tempat animasi dijalankan. Karena alasan ini, penggunaan animasi yang menggunakan banyak resource dapat berdampak negatif pada performa aplikasi Anda.
Pekerjaan yang diperlukan untuk menganimasikan UI Anda ditambahkan ke tahap animasi pipeline rendering. Anda dapat mengetahui apakah animasi memengaruhi performa aplikasi dengan mengaktifkan Rendering GPU Profil dan memantau tahap animasi. Untuk informasi selengkapnya, lihat Panduan rendering GPU profil.