MotionLayout ile hareketleri ve widget animasyonunu yönetme

MotionLayout, uygulamanızda hareketi ve widget animasyonunu yönetmenize yardımcı olan bir düzen türüdür. ConstraintLayout sınıfının alt sınıfı olan MotionLayout, zengin düzen özelliklerinden yararlanır. ConstraintLayout kitaplığının bir parçası olarak 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 animasyon çerçevesi, TransitionManager ve CoordinatorLayout arasında bir dizi özellik sunar.

Şekil 1. Temel dokunmatik kontrollü hareket.

MotionLayout, düzenler arasındaki geçişleri açıklamanın yanı sıra tüm düzen özelliklerini animasyonlu hale getirmenize olanak tanır. Üstelik, yapısı gereği aranabilir geçişleri destekler. Bu, dokunma girişi gibi belirli koşullara göre geçiş içindeki herhangi bir noktayı anında gösterebileceğiniz anlamına gelir. MotionLayout, anahtar kareleri de destekler. Böylece, ihtiyaçlarınıza göre tamamen özelleştirilmiş geçişler yapabilirsiniz.

MotionLayout tamamen açıklayıcıdır. Yani ne kadar karmaşık olursa olsun tüm geçişleri XML'de tanımlayabilirsiniz.

Tasarımla ilgili dikkat edilmesi gereken noktalar

MotionLayout, kullanıcıların etkileşimde bulunduğu kullanıcı arayüzü öğelerini (ör. düğmeler ve başlık çubuğu) taşımak, yeniden boyutlandırmak ve animasyonlu hale getirmek için tasarlanmıştır. Uygulamanızda hareketi nedensiz özel efekt olarak kullanmayın. Bunu, kullanıcıların uygulamanızın neler yaptığını anlamalarına yardımcı olmak için kullanın. Uygulamanızı hareketle tasarlama hakkında daha fazla bilgi için Hareketi anlama başlıklı Materyal Tasarım bölümüne bakın.

Başlayın

Projenizde MotionLayout ürününü 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ık

    Eski

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

    Kotlin

    dependencies {
        implementation("androidx.constraintlayout:constraintlayout:2.2.0-beta01")
        // To use constraintlayout in compose
        implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-beta01")
    }
    
  2. MotionLayout dosyası oluşturun: MotionLayout, ConstraintLayout sınıfının alt sınıfıdır. Bu nedenle, aşağıdaki örneklerde gösterildiği gibi, düzen kaynak dosyanızdaki sınıf adını değiştirerek mevcut tüm 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 aşağıda 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şturun: Önceki MotionLayout örneğinde, app:layoutDescription özelliği bir hareket sahnesine referans veriyor. Hareketli sahne, bir XML kaynak dosyasıdır. Hareket sahnesi, <MotionScene> kök öğesinde ilgili düzenin 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 atıfta bulunur. Hareket sahnesindeki tanımlar, MotionLayout'teki benzer tanımlara göre önceliklidir.

    Aşağıda, 1. resimdeki temel yatay hareketi açıklayan bir hareket sahnesi örneği verilmiştir:

    <?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ının referanslarıdır. Bu uç noktalar, hareket sahnesinin sonraki kısımlarında bulunan <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ğini gösterir.

      • motion:dragDirection, sürüklemenin ilerleme yönünü ifade eder. Örneğin, motion:dragDirection="dragRight", görünüm sağa sürüklenirken ilerlemenin arttığını gösterir.

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

    Hareket sahnesinin desteklediği çeşitli öğelere daha ayrıntılı bir bakış için MotionLayout örneklerine bakın.

İnterpole edilen özellikler

Hareketli sahne dosyasında ConstraintSet öğeleri, geçiş sırasında ara değere sahip olan ek özellikler içerebilir. Konum ve sınırlara ek olarak aşağıdaki özellikler MotionLayout tarafından ara değer olarak hesaplanır:

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

Özel özellikler

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

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

<CustomAttribute> öğesinin iki özelliği vardır:

  • motion:attributeName gereklidir ve alıcı ve belirleyici yöntemleriyle bir nesneyle eşleşmelidir. Geter ve setter belirli bir kalıpla eşleşmelidir. Örneğin, görünümde temel getBackgroundColor() ve setBackgroundColor() yöntemleri bulunduğ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:
    • Renkler için motion:customColorValue
    • Tam sayılar için motion:customIntegerValue
    • Kayan reklamlar için motion:customFloatValue
    • Dizeler için motion:customStringValue
    • Boyutlar için motion:customDimension
    • Booleler için motion:customBoolean

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

Arka plan rengini değiştir

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

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

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

MotionLayout, önceki örnekteki özelliklere ek olarak belirtmek isteyebileceğiniz başka özelliklere de sahiptir:

  • app:applyMotionScene="boolean", hareket sahnesinin uygulanıp uygulanmayacağını belirtir. true, bu özellik için varsayılan değerdir.
  • app:showPaths="boolean", hareket çalışırken hareket yollarının gösterilip gösterilmeyeceğini belirtir. Bu özelliğin varsayılan değeri false.
  • app:progress="float", geçiş ilerleme durumunu 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".

Ek kaynaklar

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