Google berkomitmen untuk mendorong terwujudnya keadilan ras bagi komunitas Kulit Hitam. Lihat caranya.

Mengelola animasi gerakan dan widget dengan MotionLayout

MotionLayout adalah jenis tata letak yang membantu Anda mengelola animasi gerakan dan widget di aplikasi Anda. MotionLayout adalah subclass dari ConstraintLayout dan dibuat berdasarkan pada kemampuan tata letaknya yang kaya. Sebagai bagian dari library ConstraintLayout, MotionLayout tersedia sebagai support library dan kompatibel dengan versi API di bawah API level 14.

Gambar 1. Gerakan dasar yang dikontrol sentuhan.

MotionLayout menghubungkan celah antara penanganan gerakan yang kompleks dan transisi tata letak, yang menawarkan perpaduan fitur antara framework animasi properti, TransitionManager, dan CoordinatorLayout.

Selain menjelaskan transisi antara tata letak, MotionLayout juga memungkinkan Anda menganimasikan properti tata letak apa pun. Selain itu, kode tersebut pada dasarnya mendukung transisi yang dapat dicari. Artinya, Anda dapat langsung menampilkan titik apa pun dalam transisi berdasarkan beberapa ketentuan, seperti masukan sentuh. MotionLayout juga mendukung bingkai utama, sehingga memungkinkan transisi yang sepenuhnya disesuaikan agar sesuai dengan kebutuhan Anda.

MotionLayout sepenuhnya bersifat deklaratif, artinya Anda dapat menjelaskan transisi apa pun dalam XML, terlepas dari seberapa besar kompleksitasnya.

Pertimbangan desain

MotionLayout ditujukan untuk memindahkan, mengubah ukuran, dan menganimasikan elemen UI yang digunakan pengguna untuk berinteraksi, seperti tombol dan baris judul. Gerakan di aplikasi Anda seharusnya tidak hanya dilengkapi dengan efek khusus tanpa alasan. Gerakan tersebut harus digunakan untuk membantu pengguna memahami hal yang dilakukan aplikasi Anda. Untuk mengetahui informasi selengkapnya terkait cara mendesain aplikasi dengan gerakan, lihat bagian Desain Material di Memahami gerakan.

Memulai

Ikuti langkah-langkah ini untuk mulai menggunakan MotionLayout di project Anda.

  1. Tambahkan dependensi ConstraintLayout: Untuk menggunakan MotionLayout di project Anda, tambahkan dependensi 2.0 ConstraintLayout ke file build.gradle aplikasi Anda. Jika Anda menggunakan AndroidX, tambahkan dependensi berikut:

        dependencies {
            implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1'
        }
            

    Jika Anda tidak menggunakan AndroidX, tambahkan dependensi support library berikut:

        dependencies {
            implementation 'com.android.support.constraint:constraint-layout:2.0.0-beta1'
        }
            
  2. Membuat file MotionLayout: MotionLayout adalah subclass dari ConstraintLayout, sehingga Anda dapat mengubah ConstraintLayout apa pun yang ada menjadi MotionLayout dengan mengganti nama class di file resource tata letak Anda, seperti yang ditunjukkan dalam contoh berikut:

    AndroidX

        <!-- before: ConstraintLayout -->
        <androidx.constraintlayout.widget.ConstraintLayout .../>
        <!-- after: MotionLayout -->
        <androidx.constraintlayout.motion.widget.MotionLayout .../>
                  

    Support library

        <!-- before: ConstraintLayout -->
        <android.support.constraint.ConstraintLayout .../>
        <!-- after: MotionLayout -->
        <android.support.constraint.motion.MotionLayout .../>
                  

    Berikut adalah contoh lengkap file MotionLayout yang dapat digunakan untuk membuat gerakan pada Gambar 1:

    AndroidX

        <?xml version="1.0" encoding="utf-8"?>
        <!-- activity_main.xml -->
        <androidx.constraintlayout.motion.widget.MotionLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            android:id="@+id/motionLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layoutDescription="@xml/scene_01"
            tools:showPaths="true">
    
            <View
                android:id="@+id/button"
                android:layout_width="64dp"
                android:layout_height="64dp"
                android:background="@color/colorAccent"
                android:text="Button" />
    
        </androidx.constraintlayout.motion.widget.MotionLayout>
                

    Support library

        <?xml version="1.0" encoding="utf-8"?>
        <!-- activity_main.xml -->
        <android.support.constraint.motion.MotionLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            android:id="@+id/motionLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layoutDescription="@xml/scene_01"
            tools:showPaths="true">
    
            <View
                android:id="@+id/button"
                android:layout_width="64dp"
                android:layout_height="64dp"
                android:background="@color/colorAccent"
                android:text="Button" />
    
        </android.support.constraint.motion.MotionLayout>
                
  3. Membuat MotionScene: Dalam contoh MotionLayout sebelumnya, atribut app:layoutDescription mereferensikan MotionScene. MotionScene adalah file resource XML yang berisi semua deskripsi gerakan untuk tata letak yang sesuai. Agar informasi tata letak terpisah dari deskripsi gerakan, setiap MotionLayout mereferensikan MotionScene yang terpisah. Perlu diperhatikan bahwa definisi dalam MotionScene lebih diutamakan dibandingkan definisi apa pun yang serupa dalam MotionLayout.

    Berikut contoh file MotionScene yang menjelaskan gerakan horizontal dasar pada gambar 1:

        <?xml version="1.0" encoding="utf-8"?>
        <MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:motion="http://schemas.android.com/apk/res-auto">
    
            <Transition
                motion:constraintSetStart="@+id/start"
                motion:constraintSetEnd="@+id/end"
                motion:duration="1000">
                <OnSwipe
                    motion:touchAnchorId="@+id/button"
                    motion:touchAnchorSide="right"
                    motion:dragDirection="dragRight" />
            </Transition>
    
            <ConstraintSet android:id="@+id/start">
                <Constraint
                    android:id="@+id/button"
                    android:layout_width="64dp"
                    android:layout_height="64dp"
                    android:layout_marginStart="8dp"
                    motion:layout_constraintBottom_toBottomOf="parent"
                    motion:layout_constraintStart_toStartOf="parent"
                    motion:layout_constraintTop_toTopOf="parent" />
            </ConstraintSet>
    
            <ConstraintSet android:id="@+id/end">
                <Constraint
                    android:id="@+id/button"
                    android:layout_width="64dp"
                    android:layout_height="64dp"
                    android:layout_marginEnd="8dp"
                    motion:layout_constraintBottom_toBottomOf="parent"
                    motion:layout_constraintEnd_toEndOf="parent"
                    motion:layout_constraintTop_toTopOf="parent" />
            </ConstraintSet>
    
        </MotionScene>
            

    Perhatikan hal berikut:

    • <Transition> berisi definisi dasar dari gerakan.

      • motion:constraintSetStart dan motion:constraintSetEnd adalah referensi ke endpoint gerakan. Endpoint ini kemudian didefinisikan dalam elemen <ConstraintSet> di MotionScene.

      • motion:duration menentukan jumlah milidetik yang diperlukan untuk menyelesaikan gerakan.

    • <OnSwipe> memungkinkan Anda mengontrol gerakan melalui sentuhan.

      • motion:touchAnchorId merujuk pada tampilan yang dapat Anda geser dan tarik.

      • motion:touchAnchorSide berarti bahwa kami menarik tampilan dari sisi kanan.

      • motion:dragDirection merujuk pada arah progres penarikan tampilan. Misalnya, motion:dragDirection="dragRight" berarti bahwa progres tersebut meningkat saat Anda menyeret tampilan ke sisi kanan.

    • <ConstraintSet> adalah tempat Anda menentukan berbagai kendala yang menjelaskan gerakan Anda. Dalam contoh ini, kami menentukan satu ConstraintSet untuk setiap endpoint gerakan kami. Endpoint ini dipindahkan ke tengah secara vertikal (melalui app:layout_constraintTop_toTopOf="parent" dan app:layout_constraintBottom_toBottomOf="parent"). Secara horizontal, endpoint tersebut berada di ujung sisi kiri dan kanan layar.

    Untuk mengetahui tampilan yang lebih detail pada berbagai elemen yang didukung MotionScene, lihat contoh MotionLayout.

Atribut yang diinterpolasi

Dalam file MotionScene, elemen ConstraintSet dapat berisi atribut tambahan yang diinterpolasi selama transisi. Selain posisi dan batas, atribut berikut diinterpolasi oleh MotionLayout:

  • alpha
  • visibility
  • elevation
  • rotation, rotationX, rotationY
  • translationX, translationY, translationZ
  • scaleX, scaleY

Atribut khusus

Dalam <Constraint>, Anda dapat menggunakan elemen <CustomAttribute> untuk menentukan transisi atribut yang tidak hanya terkait dengan atribut View atau posisi.

    <Constraint
        android:id="@+id/button" ...>
        <CustomAttribute
            motion:attributeName="backgroundColor"
            motion:customColorValue="#D81B60"/>
    </Constraint>
    

Satu <CustomAttribute> berisi dua atributnya sendiri:

  • motion:attributeName diperlukan dan harus cocok dengan objek menggunakan metode penyetel dan pengambil. Setter dan getter sangat cocok dengan pola tertentu. Misalnya, backgroundColor didukung, karena tampilan kami memiliki metode getBackgroundColor() dan setBackgroundColor() yang mendasarinya.
  • Atribut lain yang harus Anda berikan didasarkan pada jenis nilai. Pilih dari jenis yang didukung berikut:
    • motion:customColorValue untuk warna
    • motion:customIntegerValue untuk bilangan bulat
    • motion:customFloatValue untuk float
    • motion:customStringValue untuk string
    • motion:customDimension untuk dimensi
    • motion:customBoolean untuk boolean

Perlu diperhatikan bahwa saat menentukan atribut khusus, Anda harus menentukan nilai endpoint di elemen <ConstraintSet> awal dan akhir.

Contoh: Mengubah warna latar belakang

Berdasarkan contoh kami sebelumnya, mari lihat warna perubahan tampilan sebagai bagian dari gerakannya, seperti yang ditunjukkan pada gambar 2.

Gambar 2. Tampilan mengubah warna latar belakangnya saat bergerak.

Tambahkan elemen <CustomAttribute> untuk setiap elemen ConstraintSet, seperti yang ditunjukkan di bawah:

    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/button"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginStart="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="backgroundColor"
                motion:customColorValue="#D81B60" />
        </Constraint>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/button"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginEnd="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="backgroundColor"
                motion:customColorValue="#9999FF" />
        </Constraint>
    </ConstraintSet>
    

Atribut MotionLayout tambahan

Selain atribut dalam contoh di atas, MotionLayout memiliki atribut lain yang mungkin ingin Anda tentukan:

  • app:applyMotionScene="boolean" menunjukkan apakah akan menerapkan MotionScene atau tidak. Nilai default untuk atribut ini adalah true.
  • app:showPaths="boolean" menunjukkan apakah akan menampilkan jalur gerak saat gerakan sedang berjalan. Nilai default untuk atribut ini adalah false.
  • app:progress="float" memungkinkan Anda menentukan progres transisi secara eksplisit. Anda dapat menggunakan nilai titik mengambang dari 0 (awal transisi) ke 1 (akhir transisi).
  • app:currentState="reference" memungkinkan Anda menentukan ConstraintSet tertentu.
  • app:motionDebug memungkinkan Anda menampilkan informasi debug tambahan tentang gerakan. Kemungkinan nilainya adalah "SHOW_PROGRESS", "SHOW_PATH", atau "SHOW_ALL".

Resource lainnya

Untuk mengetahui informasi selengkapnya MotionLayout, lihat link berikut: