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 memanfaatkan fitur kemampuan tata letak. Sebagai bagian dari library ConstraintLayout, MotionLayout tersedia sebagai library dukungan.

MotionLayout menjembatani kesenjangan antara transisi tata letak dan gerakan kompleks penanganan, yang menawarkan perpaduan fitur antara animasi properti Google Cloud Platform, TransitionManager, dan CoordinatorLayout.

Gambar 1. Gerakan dasar yang dikontrol sentuhan.

Selain menjelaskan transisi antar-tata letak, MotionLayout memungkinkan Anda menganimasikan properti tata letak apa pun. Selain itu, layanan ini secara inheren mendukung fitur yang dapat dicari ini. Artinya, Anda dapat langsung menampilkan titik mana pun dalam transisi berdasarkan beberapa kondisi, misalnya input sentuh. MotionLayout juga mendukung keyframe, memungkinkan transisi yang sepenuhnya disesuaikan dengan kebutuhan Anda.

MotionLayout sepenuhnya deklaratif, artinya Anda dapat menjelaskan transisi apa pun di XML, tidak peduli seberapa rumitnya.

Pertimbangan desain

MotionLayout dimaksudkan untuk memindahkan, mengubah ukuran, dan menganimasikan elemen UI yang digunakan berinteraksi dengan pengguna, seperti tombol dan bilah judul. Jangan gunakan {i>motion <i}di aplikasi Anda sebagai efek khusus yang serampangan. Gunakan untuk membantu pengguna memahami apa aplikasi Anda lakukan. Untuk informasi selengkapnya tentang mendesain aplikasi dengan {i>motion, <i}lihat Bagian Desain Material Memahami gerakan.

Memulai

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

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

    Groovy

    dependencies {
        implementation "androidx.constraintlayout:constraintlayout:2.2.0-alpha14"
        // To use constraintlayout in compose
        implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha14"
    }
    

    Kotlin

    dependencies {
        implementation("androidx.constraintlayout:constraintlayout:2.2.0-alpha14")
        // To use constraintlayout in compose
        implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha14")
    }
    
  2. Buat file MotionLayout: MotionLayout adalah subclass dari ConstraintLayout, sehingga Anda dapat mengubah ConstraintLayout yang ada ke dalam MotionLayout dengan mengganti nama class di file resource tata letak Anda, seperti yang ditampilkan 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 dari file MotionLayout, yang menentukan tata letak yang ditampilkan dalam 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: di MotionLayout sebelumnya contoh, atribut app:layoutDescription mereferensikan adegan gerakan. Suasana gerakan adalah file resource XML. Dalam <MotionScene> elemen root, adegan gerak berisi semua deskripsi gerakan untuk tata letak yang sesuai. Untuk menjaga agar informasi tata letak tetap terpisah dari {i>motion<i} deskripsi, setiap MotionLayout mereferensikan gerakan terpisah latar depan. Definisi dalam adegan gerak lebih diprioritaskan daripada definisi apa pun yang serupa dalam MotionLayout.

    Berikut adalah contoh file scene gerakan yang menjelaskan gaya horizontal dasar {i>motion <i}di 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 titik akhir gerak. Endpoint ini didefinisikan dalam Elemen <ConstraintSet> nanti di adegan gerakan.

      • motion:duration menentukan jumlah milidetik yang dibutuhkan untuk menyelesaikan {i>motion.<i}

    • <OnSwipe> memungkinkan Anda membuat kontrol sentuh untuk gerakan.

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

      • motion:touchAnchorSide berarti tampilan ditarik dari sisi kanan.

      • motion:dragDirection merujuk pada progres arah penyeretan. Misalnya, motion:dragDirection="dragRight" berarti progres akan meningkat bila tampilan ditarik ke kanan.

    • <ConstraintSet> adalah tempat Anda menentukan berbagai batasan yang menjelaskan {i>motion<i} Anda. Dalam contoh ini, satu <ConstraintSet> ditentukan untuk setiap titik akhir gerakan Anda. Semua titik akhir ini dipusatkan secara vertikal menggunakan app:layout_constraintTop_toTopOf="parent" dan app:layout_constraintBottom_toBottomOf="parent". Secara horizontal, endpoint berada di sisi paling kiri dan kanan layar.

    Untuk tampilan yang lebih detail tentang berbagai elemen yang adegan gerak dukung, lihat Contoh MotionLayout.

Atribut yang diinterpolasi

Dalam file adegan gerakan, elemen ConstraintSet dapat berisi tambahan yang diinterpolasi selama transisi. Selain posisi dan batas, atribut berikut diinterpolasikan 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 untuk atribut yang tidak hanya terkait dengan posisi atau View .

<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 dengan pengambil dan metode penyetel. Pengambil dan penyetel harus cocok dengan pola tertentu. Sebagai misalnya, backgroundColor didukung, karena tampilan memiliki elemen Metode getBackgroundColor() dan setBackgroundColor().
  • Atribut lain yang harus Anda berikan didasarkan pada jenis nilai. Pilih dari jenis yang didukung berikut ini:
    • 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

Saat menentukan atribut khusus, tentukan nilai endpoint di titik awal dan elemen <ConstraintSet> akhir.

Ubah warna latar belakang

Berdasarkan contoh sebelumnya, misalkan Anda ingin warna tampilan berubah sebagai bagian dari gerakannya, seperti yang ditunjukkan pada gambar 2.

Gambar 2. Tampilan mengubah warna latar belakangnya saat bergerak.

Tambahkan elemen <CustomAttribute> ke setiap elemen ConstraintSet, seperti yang ditunjukkan di cuplikan kode berikut:

<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 sebelumnya, MotionLayout memiliki yang mungkin ingin Anda tentukan:

  • app:applyMotionScene="boolean" menunjukkan apakah akan menerapkan tampilan gerakan. Nilai default untuk atribut ini adalah true.
  • app:showPaths="boolean" menunjukkan apakah akan menampilkan jalur gerakan sebagai {i>motion <i}yang sedang berjalan. Nilai default untuk atribut ini adalah false.
  • app:progress="float" memungkinkan Anda menentukan progres transisi secara eksplisit. Anda dapat menggunakan nilai floating point 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 {i>motion <i}(gerakan). Nilai yang mungkin adalah "SHOW_PROGRESS", "SHOW_PATH", atau "SHOW_ALL".

Referensi lainnya

Untuk mengetahui informasi selengkapnya tentang MotionLayout, lihat referensi berikut: