MotionLayout ile hareketleri ve widget animasyonunu yönetme

Compose yöntemini deneyin
Jetpack Compose, Android için önerilen kullanıcı arayüzü araç setidir. Compose'da animasyonları nasıl kullanacağınızı öğrenin.

MotionLayout, uygulamanızdaki hareket ve widget animasyonunu yönetmenize yardımcı olan bir düzen türüdür. MotionLayout, ConstraintLayout sınıfının bir alt sınıfıdır ve bu sınıfın zengin düzen özelliklerini temel alır. ConstraintLayout kitaplığının bir parçası olan MotionLayout destek kitaplığı olarak kullanılabilir.

MotionLayout, düzen geçişleri ile karmaşık hareket işleme arasındaki boşluğu doldurarak özellik animasyonu çerçevesi, TransitionManager ve CoordinatorLayout arasında bir özellik karışımı sunar.

Şekil 1. Temel dokunmatik kontrollü hareket.

MotionLayout, düzenler arasındaki geçişleri açıklamanın yanı sıra düzen özelliklerini de animasyonlu hale getirmenize olanak tanır. Ayrıca, aranabilir geçişleri doğal olarak destekler. Bu, dokunma girişi gibi bir koşula bağlı olarak geçişteki herhangi bir noktayı anında gösterebileceğiniz anlamına gelir. MotionLayout ayrıca anahtar kareleri de destekler. Bu sayede, ihtiyaçlarınıza uygun tamamen özelleştirilmiş geçişler yapabilirsiniz.

MotionLayout tamamen bildirimseldir. Bu nedenle, ne kadar karmaşık olursa olsun tüm geçişleri XML'de tanımlayabilirsiniz.

Tasarım konusunda dikkat edilmesi gereken noktalar

MotionLayout, kullanıcıların etkileşimde bulunduğu düğmeler ve başlık çubukları gibi kullanıcı arayüzü öğelerini taşımak, yeniden boyutlandırmak ve animasyon eklemek için tasarlanmıştır. Uygulamanızda hareketi gereksiz bir özel efekt olarak kullanmayın. Kullanıcıların uygulamanızın ne yaptığını anlamasına yardımcı olmak için kullanın. Uygulamanızı hareketle tasarlama hakkında daha fazla bilgi için Material Design bölümündeki Understanding motion (Hareketi Anlama) başlıklı makaleyi inceleyin.

Başlayın

Projenizde MotionLayout kullanmaya başlamak için aşağıdaki adımları uygulayın.

  1. ConstraintLayout bağımlılığını ekleyin: Projenizde MotionLayout kullanmak için uygulamanızın build.gradle dosyasına ConstraintLayout 2.0 bağımlılığını ekleyin. AndroidX kullanıyorsanız aşağıdaki bağımlılığı ekleyin:

    Eski

    dependencies {
        implementation "androidx.constraintlayout:constraintlayout:2.2.1"
        // To use constraintlayout in compose
        implementation "androidx.constraintlayout:constraintlayout-compose:1.1.1"
    }

    Kotlin

    dependencies {
        implementation("androidx.constraintlayout:constraintlayout:2.2.1")
        // To use constraintlayout in compose
        implementation("androidx.constraintlayout:constraintlayout-compose:1.1.1")
    }
  2. MotionLayout dosyası oluşturun: MotionLayout, ConstraintLayout sınıfının bir alt sınıfıdır. Bu nedenle, düzen kaynağı dosyanızdaki sınıf adını aşağıdaki örneklerde gösterildiği gibi değiştirerek mevcut ConstraintLayout sınıflarını MotionLayout sınıfına dönüştürebilirsiniz:

    AndroidX

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

    Destek kitaplığı

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

    Şekil 1'de gösterilen düzeni tanımlayan bir MotionLayout dosyasının tam örneğini burada bulabilirsiniz:

    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>
            

    Destek kitaplığı

    <?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. MotionScene oluşturma: Önceki MotionLayout örneğinde, app:layoutDescription özelliği bir MotionScene'e referans veriyor. Hareket sahnesi, bir XML kaynak dosyasıdır. Bir hareket sahnesi, <MotionScene> kök öğesi içinde ilgili düzene ait tüm hareket açıklamalarını içerir. Düzen bilgilerini hareket açıklamalarından ayrı tutmak için her MotionLayout, ayrı bir hareket sahnesine referans verir. Hareket sahnesindeki tanımlar, MotionLayout içindeki benzer tanımlardan önceliklidir.

    Şekil 1'deki temel yatay hareketi açıklayan örnek bir hareket sahnesi dosyasını aşağıda bulabilirsiniz:

    <?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>
        

    Aşağıdakileri göz önünde bulundurun:

    • <Transition> hareketin temel tanımını içerir.

      • motion:constraintSetStart ve motion:constraintSetEnd, hareketin uç noktalarına referans verir. Bu uç noktalar, hareket sahnesinin ilerleyen kısımlarındaki <ConstraintSet> öğelerinde tanımlanır.

      • motion:duration, hareketin tamamlanması için gereken milisaniye sayısını belirtir.

    • <OnSwipe> hareket için dokunma kontrolü oluşturmanıza olanak tanır.

      • motion:touchAnchorId, kullanıcının kaydırıp sürükleyebileceği görünümü ifade eder.

      • motion:touchAnchorSide, görünümün sağ taraftan sürüklendiği anlamına gelir.

      • motion:dragDirection, sürüklemenin ilerleme yönünü gösterir. Örneğin, motion:dragDirection="dragRight", görünüm sağa sürüklendikçe ilerlemenin arttığı anlamına gelir.

    • <ConstraintSet> , hareketinizi tanımlayan çeşitli kısıtlamaları tanımladığınız yerdir. Bu örnekte, hareketinizin her uç noktası için bir <ConstraintSet> tanımlanır. Bu uç noktalar, app:layout_constraintTop_toTopOf="parent" ve app:layout_constraintBottom_toBottomOf="parent" kullanılarak dikey olarak ortalanır. Yatay olarak, uç noktalar ekranın en sol ve en sağ taraflarında yer alır.

    Hareket sahnesinin desteklediği çeşitli öğeler hakkında daha ayrıntılı bilgi için MotionLayout örnekleri bölümüne bakın.

İnterpolasyonlu özellikler

Bir hareket sahnesi dosyasındaki ConstraintSet öğeleri, geçiş sırasında enterpolasyon yapılan ek özellikler içerebilir. Konum ve sınırlara ek olarak aşağıdaki özellikler MotionLayout tarafından enterpolasyon yapılır:

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

Özel özellikler

<Constraint> içinde, yalnızca konum veya View özellikleriyle ilgili olmayan özellikler için bir geçiş belirtmek üzere <CustomAttribute> öğesini kullanabilirsiniz.

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

Bir <CustomAttribute> iki özelliğe sahiptir:

  • motion:attributeName gereklidir ve getter ve setter yöntemleri olan bir nesneyle eşleşmelidir. Getter ve setter belirli bir kalıpla eşleşmelidir. Örneğin, görünümde temel alınan getBackgroundColor() ve setBackgroundColor() yöntemleri olduğundan backgroundColor desteklenir.
  • Sağlamanız gereken diğer özellik, değer türüne bağlıdır. Aşağıdaki desteklenen türler arasından seçim yapın:
    • motion:customColorValue renkler için
    • Tam sayılar için motion:customIntegerValue
    • motion:customFloatValue için kayanlar
    • Dizeler için motion:customStringValue
    • motion:customDimension boyutlar için
    • motion:customBoolean Boole değerleri için

Özel bir özellik belirtirken uç nokta değerlerini hem başlangıç hem de bitiş <ConstraintSet> öğelerinde tanımlayın.

Arka plan rengini değiştirme

Önceki örnekten devam edersek, 2. şekilde gösterildiği gibi, görünümün renklerinin hareketinin bir parçası olarak değişmesini istediğinizi varsayalım.

Şekil 2. Görünüm hareket ettikçe arka plan rengi değişir.

Aşağıdaki kod snippet'inde gösterildiği gibi her ConstraintSet öğesine bir <CustomAttribute> öğesi ekleyin:

<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>

Ek MotionLayout özellikleri

Önceki örnekteki özelliklere ek olarak, MotionLayout öğesinin belirtmek isteyebileceğiniz başka özellikleri de vardır:

  • app:applyMotionScene="boolean", hareket sahnesinin uygulanıp uygulanmayacağını gösterir. Bu özelliğin varsayılan değeri true şeklindedir.
  • app:showPaths="boolean", hareket çalışırken hareket yollarının gösterilip gösterilmeyeceğini belirtir. Bu özelliğin varsayılan değeri false şeklindedir.
  • app:progress="float", geçiş ilerlemesini açıkça belirtmenize olanak tanır. 0 (geçişin başlangıcı) ile 1 (geçişin sonu) arasındaki herhangi bir kayan nokta değerini kullanabilirsiniz.
  • app:currentState="reference", belirli bir ConstraintSet belirtmenize olanak tanır.
  • app:motionDebug, hareketle ilgili ek hata ayıklama bilgilerini görüntülemenize olanak tanır. Olası değerler "SHOW_PROGRESS", "SHOW_PATH" veya "SHOW_ALL"'dir.

Ek kaynaklar

MotionLayout hakkında daha fazla bilgi için aşağıdaki kaynaklara bakın: