Membuat animasi dengan MotionLayout untuk Android
() translation by (you can also view the original English article)
Berkat fleksibilitas yang luar biasa, ConstraintLayout
widget telah menjadi "Swiss Army knife" layout untuk pengembang aplikasi Android. Namun, menambahkan animasi kompleks didalamnya, meskipun mungkin, dapat cukup memakan waktu. Itulah sebabnya mengapa Google memperkenalkan widget MotionLayout
di I/O 2018.
Widget MotionLayout
, yang sekarang bagian dari Android Support Library, extend dari ConstraintLayout
widget. Ini adalah sebuah widget yang unik yang memungkinkan Anda untuk membuat animasi dengan hanya menggunakan XML. Selain itu, itu menawarkan kendali yang mantap atas semua animasi.
Dalam tutorial ini, saya akan menunjukkan kepada Anda bagaimana untuk menambahkannya ke proyek-proyek Android Studio Anda dan membuat beberapa animasi yang berbeda-beda
Prasyarat
Untuk mengikuti tutorial ini, Anda akan memerlukan:
- Android Studio 3.1.3 atau lebih tinggi
- perangkat atau emulator yang menjalankan Android API tingkat 21 atau lebih tinggi
- pemahaman dasar tentang
ConstraintLayout
widget
1. Menambahkan dependensi
Untuk dapat menggunakan MotionLayout
widget dalam proyek Android Studio Anda, Anda harus memiliki versi terbaru dari Constraint Layout support library sebagai dependency implementation
. Selain itu, untuk menghindari konflik versi, pastikan Anda menyertakan ketergantungan untuk versi stabil terbaru v7 appcompat support library.
Dengan demikian, tambahkan kode berikut untuk modul app build.gradle file:
1 |
implementation 'com.android.support:appcompat-v7:27.0.2' |
2 |
implementation 'com.android.support.constraint:constraint-layout:2.0.0-alpha1' |
2. Menentukan Layout
MotionLayout
widget dapat melakukan segala ConstraintLayout
widget dapat lakukan. Oleh karena itu, Anda dapat dengan bebas mengganti setiap contoh keduanya Untuk sekarang, bagaimanapun, saya sarankan Anda membuat file XML baru layout dan menambahkan MotionLayout
widget itu sebagai elemen root.
1 |
<?xml version="1.0" encoding="utf-8"?>
|
2 |
<android.support.constraint.motion.MotionLayout
|
3 |
xmlns:android="https://schemas.android.com/apk/res/android" |
4 |
xmlns:app="http://schemas.android.com/apk/res-auto" |
5 |
android:layout_width="match_parent" |
6 |
android:layout_height="match_parent" |
7 |
android:id="@+id/motion_container"> |
8 |
|
9 |
<!-- More code here -->
|
10 |
|
11 |
</android.support.constraint.motion.MotionLayout>
|
Selama tutorial ini, kita akan menganimasikan ImageView
widget. Jadi tambahkan sebagai first child dari layout.
1 |
<ImageView
|
2 |
android:id="@+id/actor" |
3 |
app:srcCompat="@color/colorAccent" |
4 |
android:layout_width="wrap_content" |
5 |
android:layout_height="wrap_content" /> |
Anda bebas untuk menggunakan setiap drawable sebagai sumber ImageView
widget. Dalam kode di atas, saya menggunakan color drawable.
Selanjutnya, tambahkan tombol Anda dapat menekan untuk memulai animasi. Kode berikut memperlihatkan bagaimana posisi di pusat tata letak:
1 |
<Button
|
2 |
android:id="@+id/button" |
3 |
android:layout_width="wrap_content" |
4 |
android:layout_height="wrap_content" |
5 |
android:text="Press Me" |
6 |
app:layout_constraintBottom_toBottomOf="parent" |
7 |
app:layout_constraintEnd_toEndOf="parent" |
8 |
app:layout_constraintStart_toStartOf="parent" |
9 |
app:layout_constraintTop_toTopOf="parent" |
10 |
android:onClick="start"/> |
Selain itu, untuk memantau progress animasi, tambahkan SeekBar
widget untuk tata letak dan posisi itu di bawah tombol. Berikut adalah bagaimana:
1 |
<SeekBar
|
2 |
android:layout_width="100dp" |
3 |
android:layout_height="wrap_content" |
4 |
app:layout_constraintTop_toBottomOf="@+id/button" |
5 |
app:layout_constraintEnd_toEndOf="parent" |
6 |
app:layout_constraintStart_toStartOf="parent" |
7 |
android:layout_marginTop="10dp" |
8 |
android:id="@+id/seekbar"/> |
Terakhir, karena ada sebuah di-klik event handler yang berhubungan dengan tombol, pastikan Anda menentukan dalam activity Anda.
1 |
fun start(v: View) { |
2 |
// More code here
|
3 |
}
|
3. Membuat Motion Scene
Anda mungkin telah memperhatikan bahwa kita tidak menambahkan ketidakleluasaan widget ImageView
sedangkan menentukan tata letak. Itu karena kami akan menambahkan mereka ke motion scene. Motion secene adalah sebuah file XML yang berisi rincian tentang animasi yang Anda inginkan untuk membuat dengan MotionLayout
widget.
Untuk membuat motion secene baru, buatlah sebuah file XML resource dan menambahkan elemen MotionScene
untuk itu.
1 |
<?xml version="1.0" encoding="utf-8"?>
|
2 |
<MotionScene
|
3 |
xmlns:android="http://schemas.android.com/apk/res/android" |
4 |
xmlns:app="http://schemas.android.com/apk/res-auto"> |
5 |
|
6 |
<!-- More code here -->
|
7 |
|
8 |
</MotionScene>
|
Motion scene berisi unsur-unsur ConstraintSet
yang menentukan constraint yang harus diterapkan ke widget pada titik-titik berbeda dalam animasi. Motion secene file biasanya berisi dua constraint set: satu untuk awal animasi dan satu untuk akhir.
Kode berikut memperlihatkan bagaimana untuk membuat dua constraint set yang akan membantu MotionLayout
widget bergerak ImageView
widget dari sudut kanan bawah layar ke sudut kiri atas:
1 |
<ConstraintSet android:id="@+id/starting_set"> |
2 |
<Constraint android:id="@+id/actor" |
3 |
app:layout_constraintBottom_toBottomOf="parent" |
4 |
app:layout_constraintRight_toRightOf="parent" |
5 |
android:layout_width="60dp" |
6 |
android:layout_height="60dp" |
7 |
/>
|
8 |
</ConstraintSet>
|
9 |
|
10 |
<ConstraintSet android:id="@+id/ending_set"> |
11 |
<Constraint android:id="@+id/actor" |
12 |
app:layout_constraintTop_toTopOf="parent" |
13 |
app:layout_constraintLeft_toLeftOf="parent" |
14 |
android:layout_width="60dp" |
15 |
android:layout_height="60dp" |
16 |
/>
|
17 |
</ConstraintSet>
|
Perhatikan bahwa setiap elemen ConstraintSet
selalu harus menentukan posisi yang diinginkan dan ukuran yang diinginkan. Hal ini penting karena itu akan menimpa informasi sebelumnya ditata layout.
Untuk membantu MotionLayout
widget memahami urutan di mana constraint set yang harus diterapkan, berikutnya Anda harus membuat sebuah elemen Transition
. Dengan menggunakan atributnya intuitif bernama constraintSetStart
dan constraintSetEnd
, Anda dapat menentukan set mana harus diterapkan pertama dan yang terakhir. Elemen Transition
juga memungkinkan Anda untuk menentukan durasi animasi.
1 |
<Transition
|
2 |
android:id="@+id/my_transition" |
3 |
app:constraintSetStart="@+id/starting_set" |
4 |
app:constraintSetEnd="@+id/ending_set" |
5 |
app:duration="2000"> |
6 |
|
7 |
</Transition>
|
Pada titik ini, motion scene ini lengkap. Namun, MotionLayout
widget masih tidak menyadari hal itu. Jadi pergi kembali ke layout file XML, tambahkan atribut layoutDescription
widget, dan set nilainya ke nama file adegan gerak.
Jika nama file adegan gerak my_scene.xml, widget MotionLayout
Anda sekarang harus terlihat seperti ini:
1 |
<android.support.constraint.motion.MotionLayout
|
2 |
xmlns:android="http://schemas.android.com/apk/res/android" |
3 |
xmlns:app="http://schemas.android.com/apk/res-auto" |
4 |
xmlns:tools="http://schemas.android.com/tools" |
5 |
android:layout_width="match_parent" |
6 |
android:layout_height="match_parent" |
7 |
app:layoutDescription="@xml/my_scene" |
8 |
android:id="@+id/motion_container"> |
9 |
|
10 |
... |
11 |
|
12 |
</android.support.constraint.motion.MotionLayout>
|
4. Mulai animasi
Ketika Anda menjalankan aplikasi, MotionLayout
widget akan secara otomatis berlaku kendala yang mengatur ditetapkan dalam atribut constraintSetStart
elemen Transition
. Oleh karena itu, untuk memulai animasi, semua yang perlu Anda lakukan adalah memanggil metode transitionToEnd()
widget. Kode berikut, yang harus ditambahkan ke event di klik handler yang Anda buat pada langkah sebelumnya, menunjukkan Anda bagaimana:
1 |
motion_container.transitionToEnd() |
Pada titik ini, jika Anda menjalankan app dan tekan tombol, Anda harus dapat melihat ImageView
widget bergerak dengan lancar di layar.

5. Menangani Event Animasi
Dengan melampirkan sebuah objek TransitionListener
MotionLayout
widget, Anda dapat memantau progress animasi.
1 |
motion_container.setTransitionListener( |
2 |
object: MotionLayout.TransitionListener { |
3 |
// More code here
|
4 |
}
|
5 |
)
|
Antarmuka TransitionListener
memiliki dua metode yang abstrak, dan Android Studio akan secara otomatis menghasilkan Rintisan bertopik bagi mereka.
Metode onTransitionCompleted()
disebut ketika transisi dari satu constraint diatur ke lain selesai. Untuk sekarang, mari kita menggunakannya untuk me-reset constraint ImageView
widget dengan memanggil metode transitionToStart()
di dalamnya.
1 |
override fun onTransitionCompleted(motionLayout: MotionLayout?, |
2 |
currentId: Int) { |
3 |
if(currentId == R.id.ending_set) { |
4 |
// Return to original constraint set
|
5 |
motion_container.transitionToStart() |
6 |
}
|
7 |
}
|
Metode onTransitionChange()
ini dipanggil setiap kali perubahan progress animasi. Dengan demikian, progress adalah angka floating-point yang terletak antara nol dan satu. Kode berikut memperlihatkan bagaimana untuk memperbarui SeekBar
berdasarkan progress animasi:
1 |
override fun onTransitionChange(motionLayout: MotionLayout?, |
2 |
startId: Int, |
3 |
endId: Int, |
4 |
progress: Float) { |
5 |
seekbar.progress = ceil(progress * 100).toInt() |
6 |
}
|
Silahkan jalankan app lagi untuk melihat dua animasi sekarang.

6. Membuat Key Frames
Dalam animasi kami, ImageView
widget bergerak dalam path yang tampak seperti garis lurus. Itu adalah karena MotionLayout
widget diberikan hanya dua poin untuk bekerja dengan: titik awal, yang di bagian bawah sudut kanan layar, dan titik akhir, yang adalah di sudut kiri atas layar. Jika Anda ingin mengubah bentuk dari path, Anda harus memberikan beberapa poin menengah, yang terletak antara titik awal dan akhir. Untuk melakukannya, Anda harus membuat key frame baru.
Sebelum Anda mulai membuat key frame, Anda harus menambahkan elemen KeyFrameSet
elemen Transition
adegan gerak Anda. Di dalam element baru, Anda akan bebas untuk membuat sejumlah key frame.
1 |
<KeyFrameSet android:id="@+id/my_keys"> |
2 |
<!-- More code here -->
|
3 |
</KeyFrameSet>
|
MotionLayout
widget mendukung banyak jenis key frame. Dalam tutorial ini, kita akan bekerja dengan hanya dua tipe: KeyPosition
frame dan KeyCycle
frame.
KeyPosition
frame adalah orang-orang yang membantu Anda mengubah bentuk path. Sementara membuat mereka, pastikan Anda memberikan ID dari target widget, posisi sepanjang waktu, yang dapat menjadi nomor antara 0 dan 100, dan masukkan koordinat X atau Y yang ditentukan sebagai persentase. Koordinat dapat dibandingkan sebenarnya X atau Y kapak atau menjadi relatif terhadap jalan itu sendiri.
Kode berikut memperlihatkan bagaimana untuk membuat dua key frame yang memaksa ImageView
widget untuk mengikuti path yang menghindari tabrakan dengan tombol dan seek bar:
1 |
<KeyPosition
|
2 |
app:target="@+id/actor" |
3 |
app:framePosition="30" |
4 |
app:type="deltaRelative" |
5 |
app:percentX="0.85" /> |
6 |
|
7 |
<KeyPosition
|
8 |
app:target="@+id/actor" |
9 |
app:framePosition="60" |
10 |
app:type="deltaRelative" |
11 |
app:percentX="1" /> |
Jika Anda menjalankan app sekarang, Anda akan melihat sebuah animasi yang terlihat seperti ini:

Anda adalah, tentu saja, bebas untuk menambahkan key frame lebih. Sebagai contoh, dengan menambahkan key frame berikut menjelang akhir timeline, Anda dapat membuat widget ImageView
mengikuti path lebih bergelombang:
1 |
<KeyPosition
|
2 |
app:target="@+id/actor" |
3 |
app:framePosition="80" |
4 |
app:type="deltaRelative" |
5 |
app:percentX="0.5" /> |
Dengan menggunakan frame KeyCycle
bersama dengan KeyPosition
frame, Anda dapat menambahkan osilasi untuk animasi. Sekaligus menciptakan itu, Anda harus sekali lagi memberikan ID dari target widget, posisi sepanjang timeline, dan masukkan nilai properti yang terombang-ambing bolak. Selain itu, Anda harus mengkonfigurasi osilator dengan menyediakan rincian seperti bentuk gelombang untuk menggunakan dan periode gelombang.
Kode berikut menciptakan frame KeyCycle
yang menggunakan osilator gelombang sinus untuk secara berkala memutar ImageView
widget dengan 50 derajat:
1 |
<KeyCycle
|
2 |
app:target="@+id/actor" |
3 |
app:framePosition="30" |
4 |
android:rotation="50" |
5 |
app:waveShape="sin" |
6 |
app:wavePeriod="1" /> |
Jalankan app lagi, Anda akan melihat sebuah animasi yang terlihat seperti ini:

7. Membua tWidget Animasi interaktif
Semua saat ini, Anda telah telah menekan sebuah tombol untuk memulai animasi. Sebuah tombol, namun, ini tidak selalu diperlukan karena MotionLayout
widget memungkinkan Anda untuk langsung pasang event handler untuk widget yang sedang menjalankan animasi. Saat ini mendukung di-klik dan on-swipe event.
Misalnya, Anda dapat menambahkan elemen OnClick
berikut, yang menargetkan ImageView
widget, di dalam elemen Transition
motion scene Anda untuk membuat tombol redundant:
1 |
<OnClick
|
2 |
app:target="@+id/actor" |
3 |
app:mode="transitionToEnd"/> |
Demikian pula, Anda dapat menggunakan elemen OnSwipe
untuk memungkinkan pengguna untuk secara manual menarik ImageView
widget di layar. Sementara membuat elemen, Anda harus memastikan Anda memberikan arah drag dan sisi widget yang harus bertindak sebagai drag handle.
1 |
<OnSwipe
|
2 |
app:touchAnchorId="@+id/actor" |
3 |
app:touchAnchorSide="top" |
4 |
app:dragDirection="dragUp" /> |
Jika Anda menjalankan app lagi, Anda sekarang harus mampu men-drag ImageView
widget.

Kesimpulan
Anda sekarang tahu bagaimana cara menggunakan MotionLayout
widget untuk cepat menambahkan animasi kompleks, interaktif untuk aplikasi Android Anda. Anda dapat yakin bahwa animasi akan berjalan tanpa lag apapun atau jitter pada sebagian besar perangkat, selama anda menghindari nested view
It's worth dicatat bahwa rilis mendatang Android Studio akan mencakup gerak Editor visual, yang kemungkinan akan lebih meningkatkan kegunaan dari widget.
Untuk selengkapnya, lihat dokumentasi resmi.