Framework transisi Android memungkinkan Anda menganimasikan semua jenis gerakan di UI dengan menyediakan tata letak awal dan akhir. Anda dapat memilih jenis animasi yang diinginkan—misalnya memudarkan tampilan masuk atau keluar, atau mengubah ukuran tampilan—dan framework transisi menentukan cara menganimasikan dari tata letak awal ke tata letak akhir.
Framework transisi mencakup fitur berikut:
- Animasi tingkat grup: menerapkan efek animasi ke semua tampilan dalam hierarki tampilan.
- Animasi bawaan: menggunakan animasi yang telah ditentukan sebelumnya untuk efek umum seperti memudar atau bergerak.
- Dukungan file resource: memuat hierarki tampilan dan animasi bawaan dari file resource tata letak.
- Callback siklus proses: menerima callback yang memberikan kontrol atas animasi dan proses perubahan hierarki.
Untuk kode contoh yang menganimasikan perubahan tata letak, lihat BasicTransition.
Proses dasar untuk memberi animasi antara dua tata letak adalah sebagai berikut:
- Buat objek
Scene
untuk tata letak awal dan akhir. Namun, scene tata letak awal sering kali ditentukan secara otomatis dari tata letak saat ini. - Buat objek
Transition
untuk menentukan jenis animasi yang Anda inginkan. - Panggil
TransitionManager.go()
, dan sistem akan menjalankan animasi untuk menukar tata letak.
Diagram pada gambar 1 mengilustrasikan hubungan antara tata letak, scene, transisi, dan animasi akhir.
Membuat scene
Scene menyimpan status hierarki tampilan, termasuk semua tampilan dan nilai propertinya. Framework transisi dapat menjalankan animasi antara scene awal dan akhir.
Anda dapat membuat scene dari file resource tata letak atau dari grup tampilan dalam kode Anda. Namun, adegan awal untuk transisi Anda sering kali ditentukan secara otomatis dari UI saat ini.
Scene juga dapat menentukan tindakannya sendiri yang berjalan saat Anda membuat perubahan scene. Fitur ini berguna untuk membersihkan setelan tampilan setelah transisi ke sebuah scene.
Membuat scene dari resource tata letak
Anda dapat membuat instance Scene
langsung dari file resource
tata letak. Gunakan teknik ini saat sebagian besar hierarki tampilan dalam file bersifat statis.
Scene yang dihasilkan mewakili status hierarki tampilan pada saat Anda
membuat instance Scene
. Jika Anda mengubah hierarki tampilan,
buat ulang scene. Framework ini membuat scene dari seluruh hierarki
tampilan dalam file. Anda tidak dapat membuat scene dari bagian file tata letak.
Untuk membuat instance Scene
dari file resource tata letak, ambil
root scene dari tata letak sebagai
ViewGroup
. Selanjutnya, panggil fungsi
Scene.getSceneForLayout()
dengan root scene dan ID resource file tata letak yang
berisi hierarki tampilan untuk scene.
Menentukan tata letak untuk scene
Cuplikan kode di bagian lainnya menunjukkan cara membuat dua
scene yang berbeda dengan elemen root scene yang sama. Cuplikan tersebut juga menunjukkan
bahwa Anda dapat memuat beberapa objek Scene
yang tidak terkait tanpa menyiratkan bahwa objek tersebut
saling berkaitan.
Contoh ini terdiri dari definisi tata letak berikut:
- Tata letak utama aktivitas dengan label teks dan turunan
FrameLayout
. ConstraintLayout
untuk scene pertama dengan dua kolom teks.ConstraintLayout
untuk scene kedua dengan dua kolom teks yang sama dalam urutan yang berbeda.
Contoh ini didesain agar semua animasi muncul dalam tata letak turunan dari tata letak utama untuk aktivitas. Label teks di tata letak utama tetap statis.
Tata letak utama untuk aktivitas ini didefinisikan sebagai berikut:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/master_layout"> <TextView android:id="@+id/title" ... android:text="Title"/> <FrameLayout android:id="@+id/scene_root"> <include layout="@layout/a_scene" /> </FrameLayout> </LinearLayout>
Definisi tata letak ini berisi kolom teks dan FrameLayout
turunan untuk
root scene. Tata letak untuk scene pertama disertakan dalam file tata letak utama.
Cara ini memungkinkan aplikasi menampilkannya sebagai bagian dari antarmuka pengguna awal dan juga memuatnya
ke dalam sebuah scene, karena framework hanya dapat memuat seluruh file tata letak ke dalam
scene.
Tata letak untuk scene pertama didefinisikan sebagai berikut:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/scene_container" android:layout_width="match_parent" android:layout_height="match_parent" ></androidx.constraintlayout.widget.ConstraintLayout>
Tata letak untuk scene kedua berisi dua kolom teks yang sama—dengan ID yang sama—ditempatkan dalam urutan yang berbeda. Ini didefinisikan sebagai berikut:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/scene_container" android:layout_width="match_parent" android:layout_height="match_parent" ></androidx.constraintlayout.widget.ConstraintLayout>
Membuat scene dari tata letak
Setelah membuat definisi untuk dua tata letak batasan, Anda dapat memperoleh adegan untuk masing-masing tata letak. Hal ini memungkinkan Anda melakukan transisi antara dua konfigurasi UI. Untuk mendapatkan scene, Anda memerlukan referensi ke root scene dan ID resource tata letak.
Cuplikan kode berikut menunjukkan cara mendapatkan referensi untuk root scene dan
membuat dua objek Scene
dari file tata letak:
Kotlin
val sceneRoot: ViewGroup = findViewById(R.id.scene_root) val aScene: Scene = Scene.getSceneForLayout(sceneRoot, R.layout.a_scene, this) val anotherScene: Scene = Scene.getSceneForLayout(sceneRoot, R.layout.another_scene, this)
Java
Scene aScene; Scene anotherScene; // Create the scene root for the scenes in this app. sceneRoot = (ViewGroup) findViewById(R.id.scene_root); // Create the scenes. aScene = Scene.getSceneForLayout(sceneRoot, R.layout.a_scene, this); anotherScene = Scene.getSceneForLayout(sceneRoot, R.layout.another_scene, this);
Di aplikasi, kini ada dua objek Scene
berdasarkan hierarki
tampilan. Kedua scene menggunakan root scene yang ditentukan oleh
elemen FrameLayout
dalam res/layout/activity_main.xml
.
Membuat scene dalam kode Anda
Anda juga dapat membuat instance Scene
dalam kode Anda dari objek ViewGroup
. Gunakan teknik ini saat Anda mengubah hierarki tampilan
secara langsung dalam kode atau saat membuatnya secara dinamis.
Untuk membuat scene dari hierarki tampilan dalam kode Anda, gunakan konstruktor
Scene(sceneRoot, viewHierarchy)
. Memanggil konstruktor ini sama dengan memanggil
fungsi Scene.getSceneForLayout()
saat Anda telah meng-inflate file tata letak.
Cuplikan kode berikut menunjukkan cara membuat instance Scene
dari elemen root scene dan hierarki tampilan untuk scene dalam
kode Anda:
Kotlin
val sceneRoot = someLayoutElement as ViewGroup val viewHierarchy = someOtherLayoutElement as ViewGroup val scene: Scene = Scene(sceneRoot, viewHierarchy)
Java
Scene mScene; // Obtain the scene root element. sceneRoot = (ViewGroup) someLayoutElement; // Obtain the view hierarchy to add as a child of // the scene root when this scene is entered. viewHierarchy = (ViewGroup) someOtherLayoutElement; // Create a scene. mScene = new Scene(sceneRoot, mViewHierarchy);
Membuat tindakan scene
Framework ini memungkinkan Anda menentukan tindakan scene kustom yang dijalankan sistem saat masuk atau keluar dari scene. Dalam banyak kasus, menentukan tindakan scene kustom tidak diperlukan, karena framework akan menganimasikan perubahan antar-scene secara otomatis.
Tindakan scene berguna untuk menangani kasus berikut:
- Untuk menganimasikan tampilan yang tidak ada dalam hierarki yang sama. Anda dapat menganimasikan tampilan untuk scene awal dan akhir menggunakan tindakan scene keluar dan masuk.
- Untuk menganimasikan tampilan yang tidak dapat dianimasikan oleh framework transisi secara otomatis,
seperti objek
ListView
. Untuk mengetahui informasi selengkapnya, lihat bagian tentang batasan.
Untuk menyediakan tindakan scene kustom, tentukan tindakan Anda sebagai
objek Runnable
dan teruskan ke
fungsi
Scene.setExitAction()
atau
Scene.setEnterAction()
. Framework ini memanggil fungsi setExitAction()
pada suasana
awal sebelum menjalankan animasi transisi dan fungsi setEnterAction()
pada scene akhir setelah menjalankan animasi transisi.
Menerapkan transisi
Framework transisi merepresentasikan gaya animasi antar-scene dengan
objek Transition
. Anda dapat membuat instance Transition
menggunakan subclass
bawaan, seperti
AutoTransition
dan
Fade
, atau
menentukan transisi Anda sendiri.
Kemudian, Anda dapat menjalankan animasi antar-scene dengan meneruskan Scene
akhir dan Transition
ke TransitionManager.go()
.
Siklus proses transisi mirip dengan siklus proses aktivitas, dan merepresentasikan status transisi yang dipantau framework antara awal dan penyelesaian animasi. Saat berada dalam status siklus proses yang penting, framework akan memanggil fungsi callback yang dapat Anda terapkan untuk menyesuaikan antarmuka pengguna pada berbagai fase transisi.
Membuat transisi
Bagian sebelumnya menunjukkan cara membuat scene yang merepresentasikan status
hierarki tampilan yang berbeda. Setelah menentukan scene awal dan akhir yang
ingin diubah, buat objek Transition
yang menentukan animasi.
Framework ini memungkinkan Anda menentukan transisi bawaan dalam file resource
dan meng-inflate-nya dalam kode atau membuat instance transisi bawaan
langsung dalam kode Anda.
Class | Tag | Efek |
---|---|---|
AutoTransition |
<autoTransition/> |
Transisi default. Memudarkan, memindahkan, mengubah ukuran, serta memperjelas tampilan, dalam urutan tersebut. |
ChangeBounds |
<changeBounds/> |
Memindahkan dan mengubah ukuran tampilan. |
ChangeClipBounds |
<changeClipBounds/> |
Mengambil View.getClipBounds() sebelum dan sesudah perubahan scene dan menganimasikan perubahan tersebut selama transisi. |
ChangeImageTransform |
<changeImageTransform/> |
Menangkap matriks ImageView sebelum dan sesudah perubahan scene serta menganimasikannya selama transisi. |
ChangeScroll |
<changeScroll/> |
Menangkap properti scroll target sebelum dan setelah perubahan scene dan menganimasikan perubahan apa pun. |
ChangeTransform |
<changeTransform/> |
Menangkap skala dan rotasi tampilan sebelum dan setelah perubahan scene, serta menganimasikan perubahan tersebut selama transisi. |
Explode |
<explode/> |
Melacak perubahan pada visibilitas tampilan target di scene awal dan akhir, serta memindahkan tampilan masuk atau keluar dari tepi scene. |
Fade |
<fade/> |
fade_in memperjelas tampilan.fade_out memudarkan tampilan.fade_in_out (default) melakukan fade_out yang diikuti oleh
fade_in .
|
Slide |
<slide/> |
Melacak perubahan pada visibilitas tampilan target di scene awal dan akhir, serta memindahkan tampilan masuk atau keluar dari salah satu tepi scene. |
Membuat instance transisi dari file resource
Teknik ini memungkinkan Anda mengubah definisi transisi tanpa mengubah kode aktivitas. Teknik ini juga berguna untuk memisahkan definisi transisi yang kompleks dari kode aplikasi Anda, seperti yang ditunjukkan di bagian tentang menentukan beberapa transisi.
Untuk menentukan transisi bawaan dalam file resource, ikuti langkah-langkah berikut:
- Tambahkan direktori
res/transition/
ke project Anda. - Buat file resource XML baru di dalam direktori ini.
- Tambahkan node XML untuk salah satu transisi bawaan.
Misalnya, file resource berikut menentukan transisi Fade
:
<fade xmlns:android="http://schemas.android.com/apk/res/android" />
Cuplikan kode berikut menunjukkan cara meng-inflate instance Transition
dalam
aktivitas Anda dari file resource:
Kotlin
var fadeTransition: Transition = TransitionInflater.from(this) .inflateTransition(R.transition.fade_transition)
Java
Transition fadeTransition = TransitionInflater.from(this). inflateTransition(R.transition.fade_transition);
Membuat instance transisi dalam kode Anda
Teknik ini berguna untuk membuat objek transisi secara dinamis jika Anda mengubah antarmuka pengguna dalam kode dan untuk membuat instance transisi bawaan sederhana dengan sedikit atau tanpa parameter.
Untuk membuat instance transisi bawaan, panggil salah satu konstruktor publik
dalam subclass dari class Transition
. Misalnya, cuplikan kode berikut membuat instance transisi Fade
:
Kotlin
var fadeTransition: Transition = Fade()
Java
Transition fadeTransition = new Fade();
Menerapkan transisi
Anda biasanya menerapkan transisi untuk berubah antara hierarki tampilan yang berbeda sebagai respons terhadap peristiwa, seperti tindakan pengguna. Misalnya, pertimbangkan aplikasi penelusuran: saat pengguna memasukkan istilah penelusuran dan mengetuk tombol penelusuran, aplikasi akan berubah ke scene yang menampilkan tata letak hasil saat menerapkan transisi yang memudarkan tombol penelusuran dan memudar di hasil penelusuran.
Untuk membuat perubahan scene saat menerapkan transisi sebagai respons terhadap peristiwa dalam
aktivitas Anda, panggil fungsi class TransitionManager.go()
dengan adegan
akhir dan instance transisi yang akan digunakan untuk animasi, seperti yang ditampilkan dalam
cuplikan berikut:
Kotlin
TransitionManager.go(endingScene, fadeTransition)
Java
TransitionManager.go(endingScene, fadeTransition);
Framework mengubah hierarki tampilan di dalam root scene dengan hierarki tampilan dari scene akhir saat menjalankan animasi yang ditentukan oleh instance transisi. Adegan awal adalah adegan akhir dari transisi terakhir. Jika tidak ada transisi sebelumnya, scene awal akan ditentukan secara otomatis dari status antarmuka pengguna saat ini.
Jika Anda tidak menentukan instance transisi, pengelola transisi dapat menerapkan
transisi otomatis yang melakukan hal yang wajar pada sebagian besar situasi. Untuk
mengetahui informasi selengkapnya, lihat referensi API untuk
class
TransitionManager
.
Memilih tampilan target khusus
Framework ini menerapkan transisi ke semua tampilan dalam scene awal dan akhir
secara default. Dalam beberapa kasus, Anda mungkin hanya ingin menerapkan animasi ke subset
tampilan dalam scene. Framework ini memungkinkan Anda memilih tampilan tertentu yang ingin
dianimasikan. Misalnya, framework tidak mendukung perubahan animasi pada
objek ListView
, jadi jangan coba menganimasikannya selama transisi.
Setiap tampilan yang dianimasikan oleh transisi disebut target. Anda hanya dapat memilih target yang merupakan bagian dari hierarki tampilan yang terkait dengan scene.
Untuk menghapus satu atau beberapa tampilan dari daftar target, panggil metode
removeTarget()
sebelum memulai transisi. Untuk menambahkan hanya tampilan yang Anda tentukan ke
daftar target, panggil
fungsi
addTarget()
. Untuk informasi selengkapnya, lihat referensi API untuk
class Transition
.
Menentukan beberapa transisi
Untuk mendapatkan dampak maksimal dari animasi, cocokkan dengan jenis perubahan yang terjadi di antara adegan. Misalnya, jika Anda menghapus beberapa tampilan dan menambahkan tampilan lain di antara scene, animasi memudar atau memudar akan memberikan indikasi yang jelas bahwa beberapa tampilan tidak lagi tersedia. Jika Anda memindahkan tampilan ke titik yang berbeda di layar, sebaiknya animasikan gerakan tersebut agar pengguna mengetahui lokasi baru tampilan.
Anda tidak perlu memilih hanya satu animasi, karena framework transisi memungkinkan Anda menggabungkan efek animasi dalam kumpulan transisi yang berisi grup transisi bawaan atau kustom.
Untuk menentukan kumpulan transisi dari koleksi transisi dalam XML, buat
file resource di direktori res/transitions/
dan cantumkan transisi pada
elemen TransitionSet
. Misalnya, cuplikan berikut menunjukkan cara
menentukan kumpulan transisi yang memiliki perilaku yang sama seperti class
AutoTransition
:
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android" android:transitionOrdering="sequential"> <fade android:fadingMode="fade_out" /> <changeBounds /> <fade android:fadingMode="fade_in" /> </transitionSet>
Untuk meng-inflate transisi yang ditetapkan ke
objek TransitionSet
dalam
kode Anda, panggil
fungsi TransitionInflater.from()
dalam aktivitas Anda. Class TransitionSet
diperluas dari
class Transition
, sehingga Anda dapat menggunakannya dengan pengelola transisi seperti
instance Transition
lainnya.
Menerapkan transisi tanpa scene
Mengubah hierarki tampilan bukan satu-satunya cara untuk mengubah antarmuka pengguna Anda. Anda juga dapat membuat perubahan dengan menambahkan, mengubah, dan menghapus tampilan turunan dalam hierarki saat ini.
Misalnya, Anda dapat menerapkan interaksi penelusuran dengan
satu tata letak. Mulailah dengan tata letak yang menampilkan kolom entri penelusuran dan ikon
penelusuran. Untuk mengubah antarmuka pengguna agar menampilkan hasil, hapus tombol penelusuran saat pengguna mengetuknya dengan memanggil fungsi ViewGroup.removeView()
dan tambahkan hasil penelusuran dengan memanggil fungsi ViewGroup.addView()
.
Anda dapat menggunakan pendekatan ini jika alternatifnya adalah memiliki dua hierarki yang hampir identik. Daripada membuat dan mempertahankan dua file tata letak terpisah karena sedikit perbedaan pada antarmuka pengguna, Anda dapat memiliki satu file tata letak yang berisi hierarki tampilan yang Anda ubah dalam kode.
Jika membuat perubahan dalam hierarki tampilan saat ini dengan cara ini, Anda tidak perlu membuat scene. Sebagai gantinya, Anda dapat membuat dan menerapkan transisi antara dua status hierarki tampilan menggunakan transisi tertunda. Fitur framework transisi ini dimulai dengan status hierarki tampilan saat ini, mencatat perubahan yang Anda buat pada tampilannya, dan menerapkan transisi yang menganimasikan perubahan tersebut saat sistem menggambar ulang antarmuka pengguna.
Untuk membuat transisi yang tertunda dalam hierarki tampilan tunggal, ikuti langkah-langkah berikut:
- Saat peristiwa yang memicu transisi terjadi, panggil
fungsi
TransitionManager.beginDelayedTransition()
, yang memberikan tampilan induk dari semua tampilan yang ingin Anda ubah dan transisi yang akan digunakan. Framework menyimpan status saat ini dari tampilan turunan dan nilai propertinya. - Buat perubahan pada tampilan turunan seperti yang diminta oleh kasus penggunaan Anda. Framework ini mencatat perubahan yang Anda buat pada tampilan turunan dan propertinya.
- Saat sistem menggambar ulang antarmuka pengguna sesuai dengan perubahan Anda, framework akan menganimasikan perubahan antara status asli dan status baru.
Contoh berikut menunjukkan cara menganimasikan penambahan tampilan teks ke hierarki tampilan menggunakan transisi yang tertunda. Cuplikan pertama menunjukkan file definisi tata letak:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/mainLayout" android:layout_width="match_parent" android:layout_height="match_parent" > <EditText android:id="@+id/inputText" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" /> ... </androidx.constraintlayout.widget.ConstraintLayout>
Cuplikan berikutnya menunjukkan kode yang menganimasi penambahan tampilan teks:
Kotlin
setContentView(R.layout.activity_main) val labelText = TextView(this).apply { text = "Label" id = R.id.text } val rootView: ViewGroup = findViewById(R.id.mainLayout) val mFade: Fade = Fade(Fade.IN) TransitionManager.beginDelayedTransition(rootView, mFade) rootView.addView(labelText)
Java
private TextView labelText; private Fade mFade; private ViewGroup rootView; ... // Load the layout. setContentView(R.layout.activity_main); ... // Create a new TextView and set some View properties. labelText = new TextView(this); labelText.setText("Label"); labelText.setId(R.id.text); // Get the root view and create a transition. rootView = (ViewGroup) findViewById(R.id.mainLayout); mFade = new Fade(Fade.IN); // Start recording changes to the view hierarchy. TransitionManager.beginDelayedTransition(rootView, mFade); // Add the new TextView to the view hierarchy. rootView.addView(labelText); // When the system redraws the screen to show this update, // the framework animates the addition as a fade in.
Mendefinisikan callback siklus proses transisi
Siklus proses transisi mirip dengan siklus proses aktivitas. Hal ini mewakili
status transisi yang dipantau framework selama periode antara panggilan
ke fungsi TransitionManager.go()
dan penyelesaian
animasi. Saat berada dalam status siklus proses yang penting, framework akan memanggil callback yang ditentukan oleh antarmuka TransitionListener
.
Callback siklus proses transisi berguna, misalnya, untuk menyalin nilai properti
tampilan dari hierarki tampilan awal ke hierarki tampilan akhir
selama perubahan scene. Anda tidak bisa langsung menyalin nilai dari tampilan awalnya ke
tampilan dalam hierarki tampilan akhir, karena hierarki tampilan akhir tidak
di-inflate hingga transisi selesai. Sebagai gantinya, Anda harus menyimpan nilai
dalam variabel, lalu menyalinnya ke dalam hierarki tampilan akhir saat framework
telah menyelesaikan transisi. Agar menerima notifikasi saat transisi selesai,
implementasikan
fungsi TransitionListener.onTransitionEnd()
dalam aktivitas Anda.
Untuk informasi selengkapnya, lihat referensi API untuk
class
TransitionListener
.
Batasan
Bagian ini mencantumkan beberapa batasan framework transisi umum:
- Animasi yang diterapkan ke
SurfaceView
mungkin tidak muncul dengan benar. InstanceSurfaceView
diupdate dari thread non-UI, sehingga update mungkin tidak sinkron dengan animasi tampilan lain. - Beberapa jenis transisi tertentu mungkin tidak menghasilkan efek animasi yang diinginkan
saat diterapkan ke
TextureView
. - Class yang memperluas
AdapterView
, sepertiListView
, mengelola tampilan turunannya dengan cara yang tidak kompatibel dengan framework transisi. Jika Anda mencoba menganimasikan tampilan berdasarkanAdapterView
, tampilan perangkat mungkin akan berhenti merespons. - Jika Anda mencoba mengubah ukuran
TextView
dengan animasi, teks akan muncul ke lokasi baru sebelum ukuran objek diubah sepenuhnya. Untuk menghindari masalah ini, jangan animasikan pengubahan ukuran tampilan yang berisi teks.