Sistem animasi properti adalah kerangka kerja andal yang memungkinkan Anda menganimasikan hampir semua hal. Anda dapat menentukan animasi untuk mengubah properti objek dari waktu ke waktu, terlepas dari apakah gambar itu menarik ke layar atau tidak. Animasi properti mengubah elemen (kolom dalam objek) selama jangka waktu tertentu. Untuk menganimasikan sesuatu, Anda menentukan yang ingin Anda animasikan, seperti posisi objek di layar, berapa lama yang ingin dianimasikan, dan nilai-nilai apa yang ingin dianimasikan.
Sistem animasi properti memungkinkan Anda menentukan karakteristik animasi:
- Durasi: Anda dapat menentukan durasi animasi. Durasi defaultnya adalah 300 milidetik.
- Jenis interpolasi waktu: Anda dapat menentukan cara nilai properti dihitung sebagai fungsi waktu yang telah berlalu dari animasi saat ini.
- Jumlah dan perilaku pengulangan: Anda dapat menentukan apakah animasi akan diulang atau tidak saat mencapai akhir durasi dan berapa kali animasi akan diulang. Anda juga dapat menentukan apakah Anda ingin animasi diputar secara terbalik atau tidak. Menyetelnya ke pemutaran terbalik animasi akan maju lalu mundur berulang kali, hingga mencapai jumlah pengulangan yang ditentukan.
- Kumpulan animasi: Anda dapat mengelompokkan animasi ke dalam kumpulan logis yang diputar bersama atau secara berurutan atau setelah penundaan yang ditentukan.
- Penundaan refresh frame: Anda dapat menentukan frekuensi refresh frame animasi. Tujuan secara default diatur agar refresh setiap 10 milidetik, tetapi kecepatan refresh frame aplikasi pada akhirnya tergantung pada seberapa ramai sistem secara keseluruhan dan seberapa cepat sistem dapat melayani {i>timer<i} yang mendasarinya.
Untuk melihat contoh lengkap animasi properti, lihat
Class ChangeColor
di CustomTransition
contoh di GitHub.
Cara kerja animasi properti
Pertama-tama, mari kita bahas cara kerja animasi melalui sebuah contoh sederhana. Gambar 1 menggambarkan
objek hipotetis yang dianimasikan dengan properti x
-nya, yang mewakili
lokasi horizontal pada layar. Durasi animasi disetel ke 40 md dan jaraknya
untuk dilalui adalah 40 {i>pixel<i}. Setiap 10 md, yang merupakan kecepatan refresh frame default, objek bergerak
secara horizontal sebesar 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 dipercepat di awal animasi, dan melambat di awal animasi akhir animasi. Objek masih bergerak 40 piksel dalam 40 milidetik, tetapi tidak linier. Di kolom awal, animasi ini dipercepat hingga setengah jalan, lalu melambat dari dari setengah jalan hingga akhir animasi. Seperti yang ditunjukkan Gambar 2, jarak yang ditempuh awal dan akhir animasi lebih kurang dari di tengah.
Mari kita lihat secara detail bagaimana komponen penting dari sistem animasi properti akan menghitung animasi seperti yang diilustrasikan di atas. Gambar 3 menunjukkan bagaimana class utama bekerja sama satu sama lain.
Objek ValueAnimator
melacak pengaturan waktu animasi Anda,
seperti berapa lama animasi telah berjalan, dan nilai saat ini dari properti yang
membuat animasi.
ValueAnimator
mengenkapsulasi TimeInterpolator
, yang menentukan interpolasi animasi, dan TypeEvaluator
, yang menentukan cara menghitung nilai untuk properti yang
animasi. Misalnya, dalam Gambar 2, TimeInterpolator
yang digunakan adalah
AccelerateDecelerateInterpolator
dan TypeEvaluator
akan menjadi IntEvaluator
.
Untuk memulai animasi, buat ValueAnimator
dan berikan
nilai awal dan akhir untuk properti yang ingin dianimasikan, beserta durasi
animasinya. Saat Anda memanggil start()
, animasi
dimulai. Selama seluruh animasi, ValueAnimator
menghitung fraksi berlalu
antara 0 dan 1, berdasarkan durasi animasi dan berapa banyak waktu yang telah berlalu. Tujuan
fraksi berlalu mewakili persentase waktu yang telah diselesaikan animasi, 0 yang berarti 0%
dan 1 berarti 100%. Misalnya, pada Gambar 1, fraksi berlalu pada t = 10 ms akan menjadi 0,25
karena total durasi adalah t = 40 md.
Setelah ValueAnimator
selesai menghitung pecahan berlalu,
memanggil TimeInterpolator
yang saat ini disetel, untuk menghitung
fraksi terinterpolasi. Fraksi terinterpolasi memetakan fraksi berlalu ke
yang memperhitungkan interpolasi waktu yang ditetapkan. Misalnya, dalam Gambar 2,
karena animasi dipercepat secara perlahan, fraksi terinterpolasi, sekitar 0,15, kurang dari
fraksi berlalu, 0,25, pada t = 10 md. Pada Gambar 1, fraksi terinterpolasi selalu sama dengan
fraksi berlalu.
Saat fraksi terinterpolasi dihitung, ValueAnimator
memanggil
TypeEvaluator
yang sesuai, untuk menghitung nilai
yang Anda animasikan, berdasarkan fraksi terinterpolasi, nilai awal, dan
nilai akhir animasi. Misalnya, dalam Gambar 2, fraksi terinterpolasi adalah 0,15 pada t =
10 md, jadi nilai untuk properti pada saat itu akan menjadi 0,15 × (40 - 0), atau 6.
Perbedaan antara animasi properti dengan animasi tampilan
Sistem animasi tampilan menyediakan kemampuan untuk hanya menganimasikan View
jadi jika ingin menganimasikan objek non-View
, Anda harus mengimplementasikan
kode Anda sendiri untuk melakukannya. Sistem animasi tampilan juga terkendala
dalam kenyataan bahwa itu hanya
mengekspos beberapa aspek objek View
yang akan dianimasikan, seperti penskalaan dan
rotasi Tampilan tetapi bukan warna latar belakang, misalnya.
Kekurangan lain dari sistem animasi tampilan adalah sistem ini hanya memodifikasi Tampilan digambar, dan bukan Tampilan itu sendiri. Misalnya, jika Anda membuat animasi tombol untuk bergerak di sepanjang layar, tombol akan menggambar dengan benar, tetapi lokasi aktual tempat Anda dapat mengeklik tidak berubah, jadi Anda harus mengimplementasikan logika 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. Di tingkat 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 dapat melakukan semua yang perlu Anda lakukan, atau jika kode yang ada sudah bekerja seperti yang Anda inginkan, tidak perlu menggunakan sistem animasi properti. Hal itu mungkin juga masuk akal untuk menggunakan kedua sistem animasi untuk situasi yang berbeda jika terjadi 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 dapat menggunakan
interpolator tersebut juga
di dalam sistem animasi properti. Tabel berikut menjelaskan elemen utama
dari sistem animasi properti.
Class Animator
menyediakan struktur dasar untuk membuat
animasi. Anda biasanya tidak menggunakan class ini secara langsung karena class ini hanya memberikan sedikit
fungsionalitas yang harus diperluas untuk
mendukung sepenuhnya nilai animasi. Hal berikut
subclass memperluas Animator
:
Class | Deskripsi |
---|---|
ValueAnimator |
Mesin pengaturan waktu utama untuk animasi properti yang juga menghitung nilai untuk
properti yang akan dianimasikan. Ini memiliki semua fungsi inti
yang menghitung animasi
nilai dan berisi detail pengaturan waktu dari setiap animasi, informasi tentang apakah
animasi berulang, pemroses yang menerima peristiwa pembaruan, dan kemampuan untuk menetapkan
jenis data yang akan dievaluasi. Ada dua bagian untuk properti animasi: menghitung properti animasi
nilai dan menetapkan nilai-nilai tersebut pada objek dan properti yang sedang dianimasikan. ValueAnimator tidak melakukan bagian kedua, jadi Anda harus mendengarkannya
untuk pembaruan nilai yang dihitung oleh ValueAnimator dan
memodifikasi objek yang ingin Anda animasikan dengan logika Anda sendiri. Lihat bagian tentang
Menganimasikan dengan ValueAnimator untuk informasi selengkapnya. |
ObjectAnimator |
Subclass ValueAnimator yang memungkinkan Anda menetapkan target
dan properti objek yang akan dianimasikan. Class ini memperbarui properti yang sesuai saat
ini menghitung nilai baru untuk animasi tersebut. Anda ingin menggunakan
ObjectAnimator sepanjang waktu,
karena membuat proses animasi nilai
pada objek target jauh lebih mudah. Namun,
terkadang Anda ingin menggunakan ValueAnimator secara langsung karena ObjectAnimator memiliki beberapa batasan lainnya, seperti mewajibkan
metode pengakses yang akan
ada pada objek target. |
AnimatorSet |
Menyediakan mekanisme untuk mengelompokkan animasi bersama-sama sehingga berjalan di berhubungan satu sama lain. Anda dapat menyetel animasi untuk diputar secara bersamaan, berurutan, atau setelah penundaan yang ditentukan. Lihat bagian tentang Membuat koreografi beberapa animasi dengan Set Animator untuk informasi selengkapnya. |
{i>Evaluator<i} memberi tahu sistem animasi properti cara menghitung nilai untuk elemen
saat ini. Metrik ini mengambil data waktu yang disediakan oleh 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 Anda menganimasikan
properti objek yang bukan int , float , atau warna,
Anda harus mengimplementasikan antarmuka TypeEvaluator untuk menentukan cara
untuk menghitung nilai animasi properti objek. Anda juga dapat menentukan TypeEvaluator kustom untuk int , float , dan warna
nilai tersebut, jika Anda ingin memproses jenis
itu secara berbeda dari perilaku {i>default<i}.
Lihat bagian Menggunakan TypeEvaluator untuk informasi selengkapnya
informasi tentang cara menulis
penilai khusus (custom evaluator). |
Interpolator waktu mendefinisikan bagaimana nilai tertentu dalam sebuah animasi dihitung sebagai
fungsi waktu. Misalnya, Anda dapat menentukan animasi agar terjadi secara linear di seluruh
animasi, artinya animasi bergerak secara merata sepanjang waktu, atau Anda dapat menentukan animasi
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 tersedia tidak ada yang sesuai
kebutuhan Anda, terapkan antarmuka TimeInterpolator
, dan buat antarmuka Anda sendiri. Lihat Menggunakan interpolator untuk informasi selengkapnya tentang cara menulis
interpolator.
Class/Antarmuka | Deskripsi |
---|---|
AccelerateDecelerateInterpolator |
Interpolator yang laju perubahannya dimulai dan berakhir dengan lambat, tetapi dipercepat di tengahnya. |
AccelerateInterpolator |
Interpolator yang laju perubahannya dimulai dengan lambat, lalu mereka akan lebih cepat. |
AnticipateInterpolator |
Interpolator yang perubahannya dimulai secara mundur, lalu melejit maju. |
AnticipateOvershootInterpolator |
Interpolator yang perubahannya dimulai secara mundur, melejit maju, dan melejit 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 kembali lagi. |
TimeInterpolator |
Antarmuka yang memungkinkan Anda menerapkan interpolator sendiri. |
Menganimasikan dengan ValueAnimator
Class ValueAnimator
memungkinkan Anda menganimasikan nilai beberapa jenis untuk
durasi animasi dengan menentukan kumpulan int
, float
, atau warna
yang dapat 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 durasi 1.000 md, 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 durasi 1.000 md, saat metode start()
berjalan.
Anda dapat menggunakan nilai animasi tersebut dengan menambahkan sebuah
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); } });
Di onAnimationUpdate()
Anda dapat mengakses nilai animasi yang diperbarui dan menggunakannya dalam properti
salah satu tampilan Anda. Untuk mengetahui informasi selengkapnya tentang pemroses, lihat bagian tentang
Pemroses animasi.
Menganimasikan dengan ObjectAnimator
ObjectAnimator
adalah subclass dari ValueAnimator
(dibahas di bagian sebelumnya) dan menggabungkan pengaturan waktu
mesin dan komputasi nilai ValueAnimator
dengan kemampuan untuk
menganimasikan properti bernama dari objek target. Hal ini membuat animasi objek apa pun
jauh lebih mudah, karena Anda
tidak perlu lagi menerapkan ValueAnimator.AnimatorUpdateListener
,
karena properti animasi diperbarui secara otomatis.
Membuat instance ObjectAnimator
mirip dengan ValueAnimator
, tetapi Anda juga menentukan objek dan nama properti objek tersebut (seperti
sebuah String) beserta nilai yang akan dianimasikan antara:
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
dapat memperbarui properti
dengan benar, Anda harus melakukan hal berikut:
- Properti objek yang Anda animasikan harus memiliki fungsi penyetel (dalam camel case) dalam bentuk
set<PropertyName>()
. KarenaObjectAnimator
secara 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 dengan metode penyetel yang valid dan meneruskannya ke objek asli.
- Sebagai gantinya, gunakan
ValueAnimator
.
- Jika Anda hanya menentukan satu nilai untuk parameter
values...
di salah satu metode factoryObjectAnimator
, nilai tersebut diasumsikan sebagai nilai akhir dari animasi. Oleh karena itu, properti objek yang Anda animasikan harus memiliki fungsi pengambil yang digunakan untuk mendapatkan nilai awal animasi. Fungsi pengambil harus berada dalam 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 dapat melakukannya dionAnimationUpdate()
. Misalnya, menganimasikan properti warna sebuah objek Drawable hanya akan menyebabkan pembaruan pada ketika objek itu menggambar dirinya sendiri. Semua penyetel properti di View, sepertisetAlpha()
dansetTranslationX()
membatalkan View dengan benar, sehingga Anda tidak perlu membatalkan View saat memanggilnya metode dengan nilai baru. Untuk mengetahui informasi selengkapnya tentang pemroses, lihat bagian tentang Pemroses animasi.
Mengatur koreografi beberapa animasi dengan AnimatorSet
Dalam banyak kasus, Anda ingin memutar animasi yang
bergantung pada kapan animasi lain dimulai atau
hingga akhir. Sistem Android memungkinkan Anda memaketkan animasi bersama-sama menjadi AnimatorSet
, sehingga Anda dapat menentukan apakah akan memulai animasi atau tidak
secara bersamaan, berurutan, atau setelah penundaan tertentu. Anda juga dapat menempatkan objek AnimatorSet
di dalam objek AnimatorSet lainnya.
Cuplikan kode berikut memutar Animator
berikut
objek 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 penutup tersebut.
ValueAnimator.AnimatorUpdateListener
-
onAnimationUpdate()
- dipanggil di setiap frame animasi. Dengarkan peristiwa ini gunakan nilai yang dihitung yang dihasilkan olehValueAnimator
selama animasi. Untuk menggunakan nilai, buat kueri objekValueAnimator
diteruskan ke peristiwa untuk mendapatkan nilai animasi saat ini dengan metodegetAnimatedValue()
. Menerapkan pemroses diperlukan jika Anda menggunakanValueAnimator
.Tergantung pada properti atau objek yang dianimasikan, Anda mungkin perlu memanggil
invalidate()
pada View untuk memaksa area tersebut untuk menggambar ulang dirinya sendiri dengan nilai animasi baru. Misalnya, menganimasikan properti warna objek Drawable hanya menyebabkan pembaruan pada layar ketika 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
menerapkan antarmuka Animator.AnimatorListener
, jika Anda tidak
ingin mengimplementasikan semua metode Animator.AnimatorListener
dalam antarmuka berbasis web
yang sederhana. Class AnimatorListenerAdapter
menyediakan kolom kosong
implementasi metode yang dapat
Anda pilih untuk diganti.
Misalnya, cuplikan kode berikut membuat AnimatorListenerAdapter
hanya untuk onAnimationEnd()
telepon balik:
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 menyediakan 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
Anda akan melihat animasi yang muncul dan menghilang ketika Anda menambahkannya ke atau
menghapusnya dari ViewGroup atau saat Anda memanggil permintaan
Metode setVisibility()
dengan
VISIBLE
, INVISIBLE
, atau
GONE
. View yang tersisa di ViewGroup juga dapat
bergerak ke posisi barunya saat Anda menambah atau menghapus Tampilan. 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 yang muncul di penampung.CHANGE_APPEARING
- Flag yang menunjukkan animasi yang berjalan pada item yang berubah karena ada item baru yang muncul di penampung.DISAPPEARING
- Flag yang menunjukkan animasi yang berjalan pada item yang akan 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 untuk keempat jenis peristiwa ini guna menyesuaikan tampilannya transisi tata letak Anda atau memberi tahu sistem animasi untuk menggunakan animasi {i>default<i}.
Untuk menetapkan atribut android:animateLayoutchanges
ke true
untuk
ViewGroup melakukan hal berikut:
<LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/verticalContainer" android:animateLayoutChanges="true" />
Menyetel 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
, memanggil animasi tersebut setiap kali ditentukan
perubahan status tampilan (seperti perubahan "ditekan" atau "difokus").
StateListAnimator
dapat ditentukan dalam resource XML dengan root
Elemen <selector>
dan elemen <item>
turunan yang masing-masing menentukan
status tampilan yang berbeda yang ditentukan oleh class StateListAnimator
. Masing-masing
<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 elemen
android:stateListAnimator
sebagai berikut:
<Button android:stateListAnimator="@xml/animate_scale" ... />
Sekarang animasi yang ditentukan dalam animate_scale.xml
digunakan saat
perubahan status.
Atau, untuk menetapkan animator daftar status ke tampilan di kode Anda, gunakan metode
AnimatorInflater.loadStateListAnimator()
, dan menetapkan animator ke
tampilan Anda dengan metode View.setStateListAnimator()
.
Atau, sebagai ganti menganimasikan properti tampilan, Anda dapat memutar animasi drawable antara
perubahan status, menggunakan AnimatedStateListDrawable
.
Beberapa widget sistem di
Android 5.0 menggunakan animasi ini secara default. Contoh berikut menunjukkan bagaimana
untuk 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 Anda ingin menganimasikan jenis yang tidak dikenal oleh sistem Android, Anda dapat membuat sendiri
dengan menerapkan antarmuka TypeEvaluator
. Jenis yang
dikenal oleh sistem Android adalah int
, float
, atau warna, yang
didukung oleh jenis IntEvaluator
, FloatEvaluator
, dan ArgbEvaluator
para evaluator.
Hanya ada satu metode yang dapat diterapkan di TypeEvaluator
antarmuka, metode evaluate()
. Hal ini memungkinkan
animator yang Anda gunakan untuk mengembalikan nilai yang sesuai untuk properti animasi di
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 ValueAnimator
(atau ObjectAnimator
) berjalan, fraksi berlalu saat ini akan dihitung dari
animasi (nilai antara 0 dan 1) dan kemudian menghitung versi terinterpolasinya tergantung
interpolator apa yang
Anda gunakan. Fraksi terinterpolasi adalah apa yang diterima TypeEvaluator
melalui parameter fraction
, jadi Anda melakukan
tidak perlu memperhitungkan interpolator
saat menghitung nilai animasi.
Menggunakan Interpolator
Interpolator menentukan bagaimana nilai tertentu dalam animasi dihitung sebagai fungsi dari baik. Misalnya, Anda dapat menentukan animasi agar terjadi secara linear di seluruh animasi, artinya animasi bergerak secara merata sepanjang waktu, atau Anda dapat menentukan animasi yang akan digunakan waktu non-linear, misalnya, menggunakan percepatan atau deselerasi pada awal atau akhir animasi.
Interpolator dalam sistem animasi menerima sebuah fraksi dari Animator yang mewakili
waktu yang berlalu dari animasi. Interpolator memodifikasi fraksi ini agar sesuai dengan jenis
animasi yang disediakan. Sistem Android menyediakan seperangkat interpolator umum di
android.view.animation package
. Jika tidak ada yang sesuai dengan
Anda dapat menerapkan antarmuka TimeInterpolator
dan membuat
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 dalam animasi dan
melambat keluar darinya. 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 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 |
1000 | 1 | 1 |
Seperti yang ditampilkan tabel, LinearInterpolator
mengubah nilai
dengan kecepatan yang sama, 0,2 untuk
setiap 200 md yang berlalu. AccelerateDecelerateInterpolator
mengubah nilai 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
interpolator untuk mengontrol perilaku animasi dalam interval antara
waktu dan waktu keyframe ini.
Untuk membuat instance objek Keyframe
, Anda harus menggunakan salah satu factory
metode, ofInt()
, ofFloat()
, atau ofObject()
untuk mendapatkan jenis Keyframe
yang sesuai. Kemudian Anda memanggil
metode factory ofKeyframe()
untuk
dapatkan objek PropertyValuesHolder
. Setelah memiliki objek tersebut, Anda bisa
dapatkan 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 dan penawaran View yang disederhanakan beberapa keunggulan dibandingkan sistem animasi tampilan. Tampilan sistem animasi mengubah objek View dengan mengubah cara objek tersebut digambar. Ini adalah ditangani di penampung setiap View, karena View itu sendiri tidak memiliki properti untuk dimanipulasi. Hasilnya, View dianimasikan, tetapi objek View itu sendiri tidak berubah. Ini menghasilkan perilaku seperti objek yang masih ada di lokasi aslinya, meskipun objek itu tergambar di lokasi yang berbeda pada layar. Di Android 3.0, properti baru dan properti metode pengambil dan penyetel ditambahkan untuk menghilangkan kelemahan ini.
Sistem animasi properti
dapat menganimasikan View di layar dengan mengubah properti sebenarnya dalam objek View. Di beberapa
Selain itu, View juga otomatis memanggil invalidate()
untuk me-refresh layar setiap kali propertinya diubah. Properti baru di class View
yang memfasilitasi animasi properti adalah:
translationX
dantranslationY
: Properti ini mengontrol lokasi Tampilan terletak sebagai delta dari koordinat kiri dan atasnya yang disetel oleh tata letaknya container.rotation
,rotationX
, danrotationY
: Properti ini mengontrol rotasi dalam 2D (propertirotation
) dan 3D di sekitar titik pivot.scaleX
danscaleY
: Properti ini mengontrol penskalaan 2D Lihat di sekitar titik pivotnya.pivotX
danpivotY
: Properti ini mengontrol lokasi titik pivot, di sekitar tempat terjadinya rotasi dan transformasi penskalaan. Secara default, pivot ini titik terletak di pusat objek.x
dany
: Ini adalah properti utilitas sederhana untuk mendeskripsikan lokasi akhir View dalam penampungnya, sebagai jumlah nilai kiri dan atas, serta TranslationX dan TranslationY.alpha
: Menunjukkan transparansi alfa pada View. Nilai ini adalah 1 (buram) secara default, dengan nilai 0 yang mewakili transparansi penuh (tidak terlihat).
Untuk menganimasikan properti objek Tampilan, seperti warna atau nilai rotasinya, Anda hanya perlu adalah membuat animator properti dan menentukan properti View yang ingin Anda beranimasi. Contoh:
Kotlin
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f)
Java
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
Untuk informasi lebih lanjut tentang cara membuat animator, lihat bagian tentang membuat animasi dengan ValueAnimator dan ObjectAnimator.
Menganimasikan dengan ViewPropertyAnimator
ViewPropertyAnimator
menyediakan cara sederhana untuk menganimasikan beberapa
properti View
secara paralel, menggunakan satu Animator
dasar
. Perilakunya sangat mirip dengan ObjectAnimator
, karena memodifikasi
nilai aktual properti tampilan, tetapi lebih efisien saat menganimasikan banyak properti dengan
sekali. Selain itu, kode untuk menggunakan ViewPropertyAnimator
jauh
lebih ringkas dan
lebih mudah dibaca. Cuplikan kode berikut menunjukkan perbedaan dalam menggunakan beberapa
ObjectAnimator
objek, satu
ObjectAnimator
, dan ViewPropertyAnimator
saat
secara bersamaan menganimasikan properti x
dan y
tampilan.
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 informasi selengkapnya tentang ViewPropertyAnimator
, lihat Developer Android yang sesuai
blog
postingan.
Mendeklarasikan animasi dalam XML
Sistem animasi properti memungkinkan Anda mendeklarasikan animasi properti dengan XML, bukan secara terprogram. Dengan menentukan animasi dalam XML, Anda dapat menggunakan kembali animasi dengan mudah dalam berbagai aktivitas dan lebih mudah mengedit urutan animasi.
Untuk membedakan file animasi yang menggunakan API animasi properti baru dari yang menggunakan API
framework animasi tampilan lama,
mulai Android 3.1, Anda harus menyimpan file XML untuk animasi properti di direktori res/animator/
.
Class animasi properti berikut memiliki dukungan deklarasi XML dengan elemen tag XML berikut:
ValueAnimator
-<animator>
ObjectAnimator
-<objectAnimator>
AnimatorSet
-<set>
Untuk menemukan atribut yang dapat Anda gunakan dalam deklarasi XML, lihat Animasi resource. Contoh berikut memutar dua set animasi objek secara berurutan, dengan kumpulan 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, sebagai
yang ditunjukkan dalam 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 di 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 Animasi resource .
Efek potensial pada performa UI
Animator yang memperbarui UI menyebabkan pekerjaan rendering tambahan untuk setiap bingkai di yang akan dijalankan. Karena alasan ini, menggunakan animasi yang membutuhkan banyak resource dapat berdampak negatif terhadap performa aplikasi Anda.
Pekerjaan yang diperlukan untuk menganimasikan UI Anda ditambahkan ke tahap animasi pipeline rendering. Anda dapat mengetahui apakah animasi Anda berdampak pada performa aplikasi Anda dengan mengaktifkan Rendering GPU Profil dan memantau tahap animasi. Untuk informasi selengkapnya, lihat Rendering GPU profil panduan kami.