1. Başlamadan önce
Bu codelab, Kotlin'de İleri Düzey Android kursunun bir parçasıdır. Bu kurstan en iyi şekilde yararlanmak için codelab'leri sırayla incelemeniz önerilir ancak bu zorunlu değildir. Kursla ilgili tüm codelab'ler Advanced Android in Kotlin codelabs açılış sayfasında listelenir.
MotionLayout, Android uygulamanıza zengin hareketler eklemenizi sağlayan bir kitaplıktır. ConstraintLayout, temel alınarak geliştirilmiştir ve ConstraintLayout kullanarak oluşturduğunuz her şeyi canlandırmanıza olanak tanır.
Aynı anda birden fazla görünümün konumunu, boyutunu, görünürlüğünü, alfa değerini, rengini, yüksekliğini, dönüşünü ve diğer özelliklerini canlandırmak için MotionLayout kullanabilirsiniz. Bildirimli XML kullanarak, kodda elde edilmesi zor olan ve birden fazla görünüm içeren koordineli animasyonlar oluşturabilirsiniz.
Animasyonlar, uygulama deneyimini iyileştirmenin harika bir yoludur. Animasyonları kullanarak:
- Değişiklikleri gösterme: Durumlar arasında animasyon oluşturmak, kullanıcının kullanıcı arayüzünüzdeki değişiklikleri doğal bir şekilde takip etmesini sağlar.
- Dikkat çekin: Önemli kullanıcı arayüzü öğelerine dikkat çekmek için animasyonlar kullanın.
- Güzel tasarımlar oluşturun: Tasarımdaki etkili hareketler, uygulamaların kusursuz görünmesini sağlar.
Ön koşullar
Bu codelab, Android geliştirme konusunda deneyimli geliştiriciler için tasarlanmıştır. Bu codelab'i tamamlamaya çalışmadan önce şunları yapmanız gerekir:
- Android Studio'yu kullanarak etkinlik ve temel düzen içeren bir uygulama oluşturmayı ve bunu cihazda veya emülatörde çalıştırmayı öğrenin.
ConstraintLayouthakkında bilgi sahibi olun.ConstraintLayouthakkında daha fazla bilgi edinmek için Constraint Layout codelab'ini inceleyin.
Yapacaklarınız
ConstraintSetsveMotionLayoutile animasyon tanımlama- Sürükleme etkinliklerine göre animasyon oluşturma
- Animasyonu
KeyPositionile değiştirme KeyAttributeile özellikleri değiştirme- Kodla animasyon çalıştırma
- Daraltılabilir başlıkları
MotionLayoutile canlandırma
Gerekenler
- Android Studio 4.0 (
MotionLayoutdüzenleyici yalnızca bu Android Studio sürümüyle çalışır.)
2. Başlarken
Örnek uygulamayı indirmek için:
... veya aşağıdaki komutu kullanarak GitHub deposunu komut satırından klonlayın:
$ git clone https://github.com/googlecodelabs/motionlayout.git
3. MotionLayout ile animasyon oluşturma
İlk olarak, kullanıcının tıklamalarına yanıt olarak bir görünümü ekranın üst kısmından alt kısmına taşıyan bir animasyon oluşturacaksınız.
Başlangıç kodundan animasyon oluşturmak için aşağıdaki temel parçalara ihtiyacınız vardır:
ConstraintLayoutalt sınıfı olan birMotionLayout,.MotionLayoutetiketi içinde animasyon uygulanacak tüm görünümleri belirtirsiniz.MotionScene,,MotionLayout.için bir animasyonu açıklayan bir XML dosyasıdır.- Animasyon süresini, tetikleyiciyi ve görünümlerin nasıl taşınacağını belirten
MotionSceneöğesinin bir parçası olanTransition,. - Geçişin hem başlangıç hem de bitiş kısıtlamalarını belirten bir
ConstraintSet.
MotionLayout ile başlayarak bunların her birini sırayla inceleyelim.
1. adım: Mevcut kodu inceleyin
MotionLayout, ConstraintLayout öğesinin bir alt sınıfı olduğundan animasyon eklerken aynı özelliklerin tümünü destekler. MotionLayout özelliğini kullanmak için ConstraintLayout. özelliğini kullanacağınız yere MotionLayout görünümü ekleyin
res/layoutbölümündeactivity_step1.xml.simgesini açın. Burada, içinde renk tonu uygulanmış tek birImageViewyıldız bulunanConstraintLayoutsimgesi yer alır.
activity_step1.xml
<!-- initial code -->
<androidx.constraintlayout.widget.ConstraintLayout
...
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView
android:id="@+id/red_star"
...
/>
</androidx.constraintlayout.motion.widget.MotionLayout>
Bu ConstraintLayout üzerinde herhangi bir kısıtlama yoktur. Bu nedenle, uygulamayı şimdi çalıştırırsanız yıldızların kısıtlanmamış şekilde gösterildiğini görürsünüz. Bu da yıldızların bilinmeyen bir konumda yerleştirileceği anlamına gelir. Android Studio, kısıtlamaların olmamasıyla ilgili sizi uyarır.
2. adım: Motion Layout'a dönüştürme
MotionLayout, kullanarak animasyon oluşturmak için ConstraintLayout öğesini MotionLayout öğesine dönüştürmeniz gerekir.
Düzeninizin hareketli sahne kullanması için bu sahneyi işaret etmesi gerekir.
- Bunu yapmak için tasarım yüzeyini açın. Android Studio 4.0'da, bir düzen XML dosyasına bakarken sağ üstteki bölme veya tasarım simgesini kullanarak tasarım yüzeyini açarsınız.

- Tasarım yüzeyini açtıktan sonra önizlemeyi sağ tıklayın ve Convert to MotionLayout'u (MotionLayout'a dönüştür) seçin.

Bu işlem, ConstraintLayout etiketini MotionLayout etiketiyle değiştirir ve MotionLayout etiketine @xml/activity_step1_scene. öğesini işaret eden bir motion:layoutDescription ekler.
activity_step1**.xml**
<!-- explore motion:layoutDescription="@xml/activity_step1_scene" -->
<androidx.constraintlayout.motion.widget.MotionLayout
...
motion:layoutDescription="@xml/activity_step1_scene">
Hareket sahnesi, MotionLayout içindeki bir animasyonu açıklayan tek bir XML dosyasıdır.
MotionLayout'e dönüştürdüğünüz anda tasarım yüzeyinde Motion Editor gösterilir.

Motion Editor'da üç yeni kullanıcı arayüzü öğesi bulunur:
- Genel bakış: Bu, animasyonun farklı bölümlerini seçmenize olanak tanıyan bir modal seçimdir. Bu resimde
startConstraintSetseçilmiştir. Ayrıca, aralarındaki oku tıklayarakstartileendarasındaki geçişi de seçebilirsiniz. - Bölüm: Genel bakışın altında, şu anda seçili olan genel bakış öğesine göre değişen bir bölüm penceresi bulunur. Bu resimde,
startConstraintSetbilgileri seçim penceresinde gösterilmektedir. - Özellik: Özellik paneli, genel bakış veya seçim penceresinden seçilen öğenin özelliklerini gösterir ve düzenlemenize olanak tanır. Bu resimde,
startConstraintSetiçin özellikler gösterilmektedir.
3. adım: Başlangıç ve bitiş kısıtlamalarını tanımlayın
Tüm animasyonlar başlangıç ve bitiş olarak tanımlanabilir. Başlangıç, animasyondan önce ekranın nasıl göründüğünü, bitiş ise animasyon tamamlandıktan sonra ekranın nasıl göründüğünü açıklar. MotionLayout, başlangıç ve bitiş durumu arasında (zaman içinde) nasıl animasyon yapılacağını belirlemekten sorumludur.
MotionScene, başlangıç ve bitiş durumlarını tanımlamak için ConstraintSet etiketini kullanır. ConstraintSet, görünümlere uygulanabilen bir kısıtlama grubudur. Genişlik, yükseklik ve ConstraintLayout kısıtlamaları buna dahildir. Ayrıca alpha gibi bazı özellikler de içerir. Görünümlerin kendisini değil, yalnızca bu görünümlerle ilgili kısıtlamaları içerir.
ConstraintSet içinde belirtilen tüm kısıtlamalar, düzen dosyasında belirtilen kısıtlamaları geçersiz kılar. Hem düzende hem de MotionScene içinde kısıtlamalar tanımlarsanız yalnızca MotionScene içindeki kısıtlamalar uygulanır.
Bu adımda, yıldız görünümünü ekranın üst kısmından başlayıp alt kısmında bitecek şekilde sınırlayacaksınız.
Bu adımı Motion Editor'ı kullanarak veya doğrudan activity_step1_scene.xml metnini düzenleyerek tamamlayabilirsiniz.
- Genel bakış panelinde
startConstraintSet'i seçin.

- Seçim panelinde
red_starsimgesini seçin. Şu andalayoutKaynağı gösteriliyor. Bu,ConstraintSetiçinde sınırlanmadığı anlamına gelir. Sağ üstteki kalem simgesini kullanarak Kısıtlama Oluşturun.

- Genel bakış panelinde
startConstraintSetseçildiğindered_starsimgesininstartKaynağı gösterdiğini doğrulayın. - Özellikler panelinde,
red_starseçiliykenstartConstraintSet, üst kısma bir kısıtlama ekleyin ve mavi + düğmelerini tıklayarak başlayın.

- Motion Editor'ın bu kısıtlama için oluşturduğu kodu görmek üzere
xml/activity_step1_scene.xmlsimgesini açın.
activity_step1_scene.xml
<!-- Constraints to apply at the start of the animation -->
<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@+id/red_star"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
ConstraintSet, @id/start id değerine sahip ve MotionLayout içindeki tüm görünümlere uygulanacak tüm kısıtlamaları belirtir. Bu MotionLayout yalnızca bir görünüme sahip olduğundan yalnızca bir Constraint gerekir.
ConstraintSet içindeki Constraint, activity_step1.xml içinde tanımlanan @id/red_star görünümünün kimliğini belirtir. Constraint etiketlerinin yalnızca kısıtlamaları ve düzen bilgilerini belirttiğini unutmayın. Constraint etiketi, ImageView öğesine uygulandığını bilmiyor.
Bu kısıtlama, red_star görünümünü üst öğesinin en üst başlangıcına kısıtlamak için gereken yüksekliği, genişliği ve diğer iki kısıtlamayı belirtir.
- Genel bakış panelinde
endConstraintSet'i seçin.

endConstraintSetiçindered_stariçinConstrainteklemek üzere daha önce yaptığınız adımları uygulayın.- Bu adımı tamamlamak için Motion Editor'ı kullanmak üzere mavi + düğmelerini tıklayarak
bottomveendöğelerine kısıtlama ekleyin.

- XML'deki kod şu şekilde görünür:
activitiy_step1_scene.xml
<!-- Constraints to apply at the end of the animation -->
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/red_star"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintBottom_toBottomOf="parent" />
</ConstraintSet>
@id/start gibi bu ConstraintSet da @id/red_star üzerinde tek bir Constraint içerir. Bu kez ekranın alt ucuyla sınırlanır.
Bunları @id/start ve @id/end olarak adlandırmanız gerekmez ancak bu şekilde adlandırmanız kolaylık sağlar.
4. adım: Geçiş tanımlayın
Her MotionScene en az bir geçiş de içermelidir. Geçiş, bir animasyonun başlangıcından sonuna kadar her bölümünü tanımlar.
Bir geçiş, geçiş için bir başlangıç ve bitiş ConstraintSet belirtmelidir. Geçişler, animasyonun nasıl değiştirileceğini başka şekillerde de belirtebilir. Örneğin, animasyonun ne kadar süreyle çalıştırılacağı veya görünümleri sürükleyerek nasıl animasyon oluşturulacağı gibi.
- Motion Editor, MotionScene dosyasını oluştururken varsayılan olarak bizim için bir geçiş oluşturdu. Oluşturulan geçişi görmek için
activity_step1_scene.xmlsimgesini açın.
activity_step1_scene.xml
<!-- A transition describes an animation via start and end state -->
<Transition
motion:constraintSetEnd="@+id/end"
motion:constraintSetStart="@id/start"
motion:duration="1000">
<KeyFrameSet>
</KeyFrameSet>
</Transition>
MotionLayout, animasyon oluşturmak için bu bilgilere ihtiyaç duyar. Her bir özelliğe bakıldığında:
- Animasyon başladığında izlenmelere
constraintSetStartuygulanır. constraintSetEnd, animasyonun sonunda görünümlere uygulanır.duration, animasyonun milisaniye cinsinden ne kadar süreceğini belirtir.
MotionLayout, başlangıç ve bitiş kısıtlamaları arasında bir yol belirleyip belirtilen süre boyunca bu yolu animasyon haline getirir.
5. adım: Motion Editor'da animasyonu önizleyin

Animasyon: Motion Editor'da geçiş önizlemesinin oynatıldığı video
- Motion Editor'ı açın ve genel bakış panelinde
startileendarasındaki oku tıklayarak geçişi seçin.

- Seçim panelinde, geçiş seçildiğinde oynatma kontrolleri ve kaydırma çubuğu gösterilir. Animasyonu önizlemek için oynat düğmesini tıklayın veya mevcut konumu sürükleyin.

6. adım: Tıklama işleyici ekleyin
Animasyonu başlatmak için bir yöntem gerekir. Bunu yapmanın bir yolu, MotionLayout öğesinin @id/red_star üzerindeki tıklama etkinliklerine yanıt vermesini sağlamaktır.
- Hareket düzenleyiciyi açın ve genel bakış panelinde başlangıç ile bitiş arasındaki oku tıklayarak geçişi seçin.

- Genel bakış paneli için araç çubuğunda
Tıklama veya kaydırma işleyicisi oluştur'u tıklayın . Bu işlem, geçişi başlatacak bir işleyici ekler. - Pop-up pencereden Click Handler'ı (Tıklama İşleyici) seçin.

- Görüntüleme İçin Tıklama'yı
red_starolarak değiştirin.

- Ekle'yi tıklayın. Tıklama işleyicisi, Motion Editor'daki Geçiş'te küçük bir nokta ile gösterilir.

- Genel bakış panelinde geçiş seçiliyken, özellikler panelinde yeni eklediğiniz OnClick işleyicisine
clickActionözelliğinitoggleolarak ekleyin.

- Hareket Düzenleyici'nin oluşturduğu kodu görmek için
activity_step1_scene.xmlsimgesini açın.
activity_step1_scene.xml
<!-- A transition describes an animation via start and end state -->
<Transition
motion:constraintSetStart="@+id/start"
motion:constraintSetEnd="@+id/end"
motion:duration="1000">
<!-- MotionLayout will handle clicks on @id/red_star to "toggle" the animation between the start and end -->
<OnClick
motion:targetId="@id/red_star"
motion:clickAction="toggle" />
</Transition>
Transition, MotionLayout öğesine <OnClick> etiketi kullanarak tıklama etkinliklerine yanıt olarak animasyonu çalıştırmasını söyler. Her bir özelliğe bakıldığında:
targetId, tıklamaları izlemek için kullanılan görünümdür.clickAction, tıklama üzerinetogglebaşlangıç ve bitiş durumu arasında geçiş yapar.clickActioniçin diğer seçenekleri dokümanlarda görebilirsiniz.
- Kodunuzu çalıştırın, 1. Adım'ı ve ardından kırmızı yıldızı tıklayarak animasyonu izleyin.
5. adım: Animasyonları kullanma
Uygulamayı çalıştırın. Yıldızı tıkladığınızda animasyonunuzun çalıştığını görmeniz gerekir.

Tamamlanan hareket sahnesi dosyası, başlangıç ve bitiş ConstraintSet noktalarını gösteren bir Transition tanımlar.
Animasyonun başlangıcında (@id/start), yıldız simgesi ekranın üst kısmının başlangıcına sabitlenir. Animasyonun sonunda (@id/end) yıldız simgesi ekranın alt kısmına sabitlenir.
<?xml version="1.0" encoding="utf-8"?>
<!-- Describe the animation for activity_step1.xml -->
<MotionScene xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<!-- A transition describes an animation via start and end state -->
<Transition
motion:constraintSetStart="@+id/start"
motion:constraintSetEnd="@+id/end"
motion:duration="1000">
<!-- MotionLayout will handle clicks on @id/star to "toggle" the animation between the start and end -->
<OnClick
motion:targetId="@id/red_star"
motion:clickAction="toggle" />
</Transition>
<!-- Constraints to apply at the end of the animation -->
<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@+id/red_star"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<!-- Constraints to apply at the end of the animation -->
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/red_star"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintBottom_toBottomOf="parent" />
</ConstraintSet>
</MotionScene>
4. Sürükleme etkinliklerine göre animasyon oluşturma
Bu adımda, animasyonu çalıştırmak için kullanıcının sürükleme etkinliğine (kullanıcı ekranı kaydırdığında) yanıt veren bir animasyon oluşturacaksınız. MotionLayout, görünümleri taşımak için dokunma etkinliklerinin yanı sıra hareketi akıcı hale getirmek için fizik tabanlı fırlatma hareketlerinin izlenmesini destekler.
1. adım: İlk kodu inceleyin
- Başlamak için mevcut bir
MotionLayoutiçeren düzen dosyasınıactivity_step2.xmlaçın. Koda göz atın.
activity_step2.xml
<!-- initial code -->
<androidx.constraintlayout.motion.widget.MotionLayout
...
motion:layoutDescription="@xml/step2" >
<ImageView
android:id="@+id/left_star"
...
/>
<ImageView
android:id="@+id/right_star"
...
/>
<ImageView
android:id="@+id/red_star"
...
/>
<TextView
android:id="@+id/credits"
...
motion:layout_constraintTop_toTopOf="parent"
motion:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.motion.widget.MotionLayout>
Bu düzen, animasyonun tüm görünümlerini tanımlar. Üç yıldız simgesi, hareket sahnesinde animasyonlu olacağı için düzende kısıtlanmaz.
Krediler, animasyon boyunca aynı yerde kaldığı ve herhangi bir özelliği değiştirmediği için TextView kısıtlamalara tabidir.
2. adım: Sahneyi canlandırın
Son animasyonda olduğu gibi, animasyon bir başlangıç ve bitiş ConstraintSet, ile bir Transition ile tanımlanır.
Başlangıç ConstraintSet'ini tanımlayın.
- Animasyonu tanımlamak için hareketli sahneyi
xml/step2.xmlaçın. - Başlangıç kısıtlaması
startiçin kısıtlamaları ekleyin. Başlangıçta üç yıldız da ekranın alt kısmında ortalanır. Sağ ve soldaki yıldızlarınalphadeğeri0.0'dir. Bu, yıldızların tamamen şeffaf ve gizli olduğu anlamına gelir.
step2.xml
<!-- TODO apply starting constraints -->
<!-- Constraints to apply at the start of the animation -->
<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@+id/red_star"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintBottom_toBottomOf="parent" />
<Constraint
android:id="@+id/left_star"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.0"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintBottom_toBottomOf="parent" />
<Constraint
android:id="@+id/right_star"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.0"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintBottom_toBottomOf="parent" />
</ConstraintSet>
Bu ConstraintSet içinde, her yıldız için bir Constraint belirtirsiniz. Her kısıtlama, animasyonun başında MotionLayout tarafından uygulanır.
Her yıldız görünümü, başlangıç, bitiş ve alt kısımla ilgili kısıtlamalar kullanılarak ekranın alt kısmında ortalanır. @id/left_star ve @id/right_star yıldızlarının her ikisinde de görünmez olmalarını sağlayan ve animasyonun başında uygulanacak ek bir alfa değeri vardır.
start ve end kısıtlama kümeleri, animasyonun başlangıcını ve bitişini tanımlar. motion:layout_constraintStart_toStartOf gibi başlangıç kısıtlamaları, bir görünümün başlangıcını başka bir görünümün başlangıcıyla kısıtlar. start adı hem hem için kullanıldığından ve her ikisi de kısıtlamalar bağlamında kullanıldığından bu durum ilk başta kafa karıştırıcı olabilir. Farkı daha net bir şekilde ifade etmek için layout_constraintStart içindeki start, görünümün "başlangıç" noktasını ifade eder. Bu nokta, soldan sağa dillerde sol, sağdan sola dillerde ise sağ taraftır. start kısıtlama grubu, animasyonun başlangıcını ifade eder.
Bitiş ConstraintSet'ini tanımlama
- Üç yıldızı
@id/credits'nin altında birlikte konumlandırmak için zincir kullanacak şekilde son kısıtlamayı tanımlayın. Ayrıca, sol ve sağ yıldızlarınalphabitiş değerini1.0olarak ayarlar.
step2.xml
<!-- TODO apply ending constraints -->
<!-- Constraints to apply at the end of the animation -->
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/left_star"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="1.0"
motion:layout_constraintHorizontal_chainStyle="packed"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintEnd_toStartOf="@id/red_star"
motion:layout_constraintTop_toBottomOf="@id/credits" />
<Constraint
android:id="@+id/red_star"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintStart_toEndOf="@id/left_star"
motion:layout_constraintEnd_toStartOf="@id/right_star"
motion:layout_constraintTop_toBottomOf="@id/credits" />
<Constraint
android:id="@+id/right_star"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="1.0"
motion:layout_constraintStart_toEndOf="@id/red_star"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintTop_toBottomOf="@id/credits" />
</ConstraintSet>
Sonuç olarak, animasyon sırasında görünümler merkezden dışa ve yukarı doğru yayılır.
Ayrıca, alpha özelliği her iki ConstraintSets'de de @id/right_start ve @id/left_star üzerinde ayarlandığından animasyon ilerledikçe her iki görünüm de yavaş yavaş belirginleşir.
Kullanıcı kaydırmasına göre animasyon oluşturma
MotionLayout, fizik tabanlı bir "hızlı kaydırma" animasyonu oluşturmak için kullanıcıların sürükleme etkinliklerini veya kaydırma işlemlerini izleyebilir. Bu nedenle, kullanıcı kaydırarak görüntülediğinde görünümler devam eder ve bir yüzeyde yuvarlanan fiziksel bir nesne gibi yavaşlar. Bu tür animasyonları Transition içindeki OnSwipe etiketiyle ekleyebilirsiniz.
OnSwipeetiketi eklemeyle ilgili YAPILACAKLAR'ı<OnSwipe motion:touchAnchorId="@id/red_star" />ile değiştirin.
step2.xml
<!-- TODO add OnSwipe tag -->
<!-- A transition describes an animation via start and end state -->
<Transition
motion:constraintSetStart="@+id/start"
motion:constraintSetEnd="@+id/end">
<!-- MotionLayout will track swipes relative to this view -->
<OnSwipe motion:touchAnchorId="@id/red_star" />
</Transition>
OnSwipe birkaç özellik içerir. Bunlardan en önemlisi touchAnchorId özelliğidir.
touchAnchorId, dokunmaya yanıt olarak hareket eden izlenen görünümdür.MotionLayout, bu görünümü kaydıran parmağın aynı mesafesinde tutar.touchAnchorSide, görünümün hangi tarafının izleneceğini belirler. Bu, yeniden boyutlandırılan, karmaşık yolları izleyen veya bir tarafı diğerinden daha hızlı hareket eden görünümler için önemlidir.dragDirection, bu animasyon için hangi yönün önemli olduğunu (yukarı, aşağı, sol veya sağ) belirler.
MotionLayout sürükleme etkinliklerini dinlediğinde işleyici, touchAnchorId tarafından belirtilen görünümde değil, MotionLayout görünümünde kaydedilir. Kullanıcı ekranda herhangi bir yerde hareket başlattığında MotionLayout, parmağı ile touchAnchorId görünümünün touchAnchorSide arasındaki mesafeyi sabit tutar. Örneğin, MotionLayout, sabitleme tarafının 100 dp uzağına dokunursa animasyon boyunca bu tarafı parmağından 100 dp uzakta tutar.
Deneyin
- Uygulamayı tekrar çalıştırın ve 2. Adım ekranını açın. Animasyonu görürsünüz.
MotionLayoutuygulamasının akışkan fizik tabanlı animasyonları nasıl gösterdiğini keşfetmek için animasyonun ortasında parmağınızı "fırlatmayı" veya bırakmayı deneyin.

MotionLayout, ConstraintLayout özelliklerini kullanarak çok farklı tasarımlar arasında zengin efektler oluşturabilir.
Bu animasyonda, başlangıçta üç görünüm de ekranın alt kısmındaki üst öğesine göre konumlandırılır. Son olarak, üç görünüm zincir şeklinde @id/credits ile ilişkili olarak konumlandırılır.
Bu çok farklı düzenlere rağmen MotionLayout, başlangıç ve bitiş arasında akıcı bir animasyon oluşturur.
5. Yolu değiştirme
Bu adımda, animasyon sırasında karmaşık bir yolu takip eden ve hareket sırasında jenerikleri canlandıran bir animasyon oluşturacaksınız. MotionLayout, KeyPosition kullanarak bir görünümün başlangıç ve bitiş arasındaki yolunu değiştirebilir.
1. adım: Mevcut kodu inceleyin
- Mevcut düzeni ve hareket sahnesini görmek için
layout/activity_step3.xmlvexml/step3.xml'ı açın.ImageViewveTextViewsimgelerinde ay ve "credits" (krediler) metni gösteriliyor. - Hareketli sahne dosyasını (
xml/step3.xml) açın.@id/start'den@id/end'e birTransitiontanımlandığını görürsünüz. Animasyon, ikiConstraintSetskullanarak ay resmini ekranın sol alt kısmından sağ alt kısmına taşıyor. Ay hareket ederkenalpha="0.0"olan jenerik metnialpha="1.0"olarak belirginleşir. - Uygulamayı şimdi çalıştırın ve 3. Adım'ı seçin. Ayı tıkladığınızda, ayın başlangıçtan sona doğrusal bir yol (veya düz bir çizgi) izlediğini görürsünüz.
2. adım: Yol hata ayıklamayı etkinleştirin
Ayın hareketine yay eklemeden önce MotionLayout'da yol hata ayıklamayı etkinleştirmeniz yararlı olur.
MotionLayout ile karmaşık animasyonlar geliştirmenize yardımcı olması için her görünümün animasyon yolunu çizebilirsiniz. Bu özellik, animasyonunuzu görselleştirmek ve hareketin küçük ayrıntılarını hassas bir şekilde ayarlamak istediğinizde yararlıdır.
- Hata ayıklama yollarını etkinleştirmek için
layout/activity_step3.xmlöğesini açın veMotionLayoutetiketinemotion:motionDebug="SHOW_PATH"öğesini ekleyin.
activity_step3.xml
<!-- Add motion:motionDebug="SHOW_PATH" -->
<androidx.constraintlayout.motion.widget.MotionLayout
...
motion:motionDebug="SHOW_PATH" >
Yol hata ayıklamayı etkinleştirdikten sonra uygulamayı tekrar çalıştırdığınızda tüm görünümlerin yollarının noktalı çizgiyle görselleştirildiğini görürsünüz.

- Daireler, bir görünümün başlangıç veya bitiş konumunu gösterir.
- Çizgiler, bir görünümün yolunu gösterir.
- Elmaslar, yolu değiştiren bir
KeyPosition'ı temsil eder.
Örneğin, bu animasyonda ortadaki daire, krediler metninin konumunu gösterir.
3. adım: Yolu değiştirin
MotionLayout içindeki tüm animasyonlar, animasyon başlamadan önce ve animasyon tamamlandıktan sonra ekranın nasıl görüneceğini tanımlayan bir başlangıç ve bir bitiş ConstraintSet ile tanımlanır. Varsayılan olarak, MotionLayout, konumu değişen her görünümün başlangıç ve bitiş konumu arasında doğrusal bir yol (düz çizgi) çizer.
Bu örnekteki ayın yörüngesi gibi karmaşık yollar oluşturmak için MotionLayout, görünümün başlangıç ve bitiş arasındaki yolunu değiştirmek üzere KeyPosition kullanır.
xml/step3.xmluygulamasını açın ve sahneyeKeyPositionekleyin.KeyPositionetiketi,Transitionetiketinin içine yerleştirilir.

step3.xml
<!-- TODO: Add KeyFrameSet and KeyPosition -->
<KeyFrameSet>
<KeyPosition
motion:framePosition="50"
motion:motionTarget="@id/moon"
motion:keyPositionType="parentRelative"
motion:percentY="0.5"
/>
</KeyFrameSet>
KeyFrameSet, Transition öğesinin alt öğesidir ve geçiş sırasında uygulanması gereken tüm KeyFrames'lerin (ör. KeyPosition) kümesidir.
MotionLayout, başlangıç ve bitiş arasındaki ay yolunu hesaplarken KeyFrameSet içinde belirtilen KeyPosition değerine göre yolu değiştirir. Uygulamayı tekrar çalıştırarak bu değişikliğin yolu nasıl değiştirdiğini görebilirsiniz.
KeyPosition, yolu nasıl değiştirdiğini açıklayan çeşitli özelliklere sahiptir. En önemlileri şunlardır:
framePosition, 0 ile 100 arasında bir sayıdır. Bu özellik, animasyonun hangi noktasındaKeyPositionözelliğinin uygulanacağını tanımlar. 1, animasyonun% 1'i tamamlandığında, 99 ise% 99'u tamamlandığında uygulanacağını gösterir. Bu nedenle, değer 50 ise tam ortada uygularsınız.motionTarget, buKeyPositionöğesinin yolu değiştirdiği görünümdür.keyPositionType, buKeyPositionöğesinin yolu nasıl değiştirdiğini gösterir.parentRelative,pathRelativeveyadeltaRelativeolabilir (sonraki adımda açıklanmıştır).percentX | percentY,framePositionkonumunda yolun ne kadar değiştirileceğini gösterir (0,0 ile 1,0 arasında değerler; negatif değerlere ve 1'den büyük değerlere izin verilir).
Bunu şu şekilde düşünebilirsiniz: "framePosition koordinatları tarafından belirlenen keyPositionTypekoordinatlarına göre motionTarget yolunu percentX veya percentY kadar hareket ettirerek değiştirin."
Varsayılan olarak MotionLayout, yolu değiştirerek oluşturulan tüm köşeleri yuvarlar. Oluşturduğunuz animasyona baktığınızda ayın, kıvrımda kavisli bir yolu izlediğini görebilirsiniz. Çoğu animasyon için bu değer kullanılır. Aksi takdirde, özelleştirmek için curveFit özelliğini belirtebilirsiniz.
Deneyin
Uygulamayı tekrar çalıştırırsanız bu adımın animasyonunu görürsünüz.

Ay, Transition içinde belirtilen bir KeyPosition boyunca hareket ettiği için bir yay izler.
<KeyPosition
motion:framePosition="50"
motion:motionTarget="@id/moon"
motion:keyPositionType="parentRelative"
motion:percentY="0.5"
/>
Bu ifadeyi KeyPosition olarak okuyabilirsiniz: "framePosition 50 (animasyonun yarısında) motionTarget @id/moon öğesinin yolunu, parentRelative (tüm MotionLayout) tarafından belirlenen koordinatlara göre 50% Y (ekranın yarısı) kadar hareket ettirerek değiştirin."
Bu nedenle, animasyonun yarısında ay, ekranda% 50 aşağıda olan bir KeyPosition içinden geçmelidir. Bu KeyPosition, X hareketini hiç değiştirmez. Bu nedenle ay, baştan sona yatay olarak hareket etmeye devam eder. MotionLayout, başlangıç ve bitiş arasında hareket ederken bu KeyPosition'dan geçen sorunsuz bir yol bulur.
Yakından bakarsanız kredi metninin ayın konumuyla sınırlı olduğunu görürsünüz. Neden dikey olarak da hareket etmiyor?

<Constraint
android:id="@id/credits"
...
motion:layout_constraintBottom_toBottomOf="@id/moon"
motion:layout_constraintTop_toTopOf="@id/moon"
/>
Ayın izlediği yolu değiştirseniz bile ayın başlangıç ve bitiş konumları dikey olarak hiç hareket etmiyor. KeyPosition, başlangıç veya bitiş konumunu değiştirmez. Bu nedenle, jenerik metni ayın son bitiş konumuyla sınırlıdır.
Jeneriklerin ay ile birlikte hareket etmesini istiyorsanız jeneriklere KeyPosition ekleyebilir veya @id/credits üzerindeki başlangıç kısıtlamalarını değiştirebilirsiniz.
Bir sonraki bölümde, MotionLayout içindeki farklı keyPositionType türlerini inceleyeceğiz.
6. keyPositionType özelliğini anlama
Son adımda, yolu ekranın% 50'si kadar kaydırmak için keyPosition türünde bir parentRelative kullandınız. keyPositionType özniteliği, MotionLayout'un yolu percentX veya percentY değerine göre nasıl değiştireceğini belirler.
<KeyFrameSet>
<KeyPosition
motion:framePosition="50"
motion:motionTarget="@id/moon"
motion:keyPositionType="parentRelative"
motion:percentY="0.5"
/>
</KeyFrameSet>
Üç farklı keyPosition türü vardır: parentRelative, pathRelative ve deltaRelative. Bir tür belirtmek, percentX ve percentY değerlerinin hesaplandığı koordinat sistemini değiştirir.
Koordinat sistemi nedir?
Koordinat sistemi, uzayda bir noktayı belirtmenin bir yolunu sunar. Ayrıca ekrandaki bir konumu tanımlamak için de kullanılırlar.
MotionLayout koordinat sistemleri Kartezyen koordinat sistemidir. Bu, iki dik çizgiyle tanımlanan bir X ve bir Y eksenine sahip oldukları anlamına gelir. Bu iki eksen arasındaki temel fark, X ekseninin ekranda bulunduğu yerdir (Y ekseni her zaman X eksenine diktir).
MotionLayout içindeki tüm koordinat sistemleri hem X hem de Y ekseninde 0.0 ile 1.0 arasında değerler kullanır. Negatif değerlere ve 1.0 değerinden büyük değerlere izin verilir. Örneğin, percentX değeri -2.0 ise X ekseninin tersi yönünde iki kez hareket etmeniz gerekir.
Bu bilgiler biraz fazla matematiksel geliyorsa aşağıdaki resimlere göz atın.
parentRelative coordinates

parentRelative öğesinin keyPositionType özelliği, ekranla aynı koordinat sistemini kullanır. (0, 0), tüm MotionLayout'nin sol üstünü, (1, 1) ise sağ altını tanımlar.
parentRelative, bu örnekteki ay yayı gibi MotionLayout boyunca hareket eden bir animasyon oluşturmak istediğinizde kullanılabilir.
Ancak bir yolu harekete göre değiştirmek (ör. yolu biraz kıvrımlı hale getirmek) istiyorsanız diğer iki koordinat sistemi daha iyi bir seçimdir.
deltaRelative koordinatları

Delta, değişim anlamına gelen bir matematik terimidir. Bu nedenle deltaRelative, "göreceli değişim" demenin bir yoludur. deltaRelative koordinatları(0,0), görünümün başlangıç konumunu, (1,1) ise bitiş konumunu ifade eder. X ve Y eksenleri ekranla hizalanır.
X ekseni ekranda her zaman yatay, Y ekseni ise her zaman dikey olur. parentRelative ile karşılaştırıldığında temel fark, koordinatların yalnızca görünümün hareket edeceği ekran bölümünü tanımlamasıdır.
deltaRelative, yatay veya dikey hareketi ayrı ayrı kontrol etmek için mükemmel bir koordinat sistemidir. Örneğin, dikey (Y) hareketini %50'de tamamlayan ve yatay (X) yönde animasyona devam eden bir animasyon oluşturabilirsiniz.
pathRelative koordinatları

MotionLayout içindeki son koordinat sistemi pathRelative. X ekseni, hareket yolunu baştan sona takip ettiğinden bu grafik diğer ikisinden oldukça farklıdır. Bu nedenle (0,0) başlangıç konumu, (1,0) ise bitiş konumudur.
Bunu neden isteyebilirsiniz? Bu koordinat sistemi, ekran koordinat sistemiyle bile hizalanmadığı için ilk bakışta oldukça şaşırtıcıdır.
pathRelative'nın birkaç konuda gerçekten faydalı olduğu ortaya çıktı.
- Animasyonun bir bölümünde görünümü hızlandırma, yavaşlatma veya durdurma. X boyutu, görünümün izlediği yolla her zaman tam olarak eşleştiğinden, bu yoldaki belirli bir noktaya hangi
framePositionile ulaşıldığını değiştirmek içinpathRelativeKeyPositionkullanabilirsiniz. Bu nedenle,percentX="0.1"ileframePosition="50"konumundaki birKeyPosition, animasyonun hareketin ilk% 10'unu tamamlaması için gereken sürenin% 50'sini kullanmasına neden olur. - Yola ince bir yay ekleme. Y boyutu her zaman harekete dik olduğundan Y'yi değiştirmek, genel harekete göre eğri yolunu değiştirir.
deltaRelativeİkinci boyut ekleme işlemi çalışmaz. Tamamen yatay ve dikey hareket içindeltaRelativeyalnızca bir faydalı boyut oluşturur. AncakpathRelativeher zaman kullanılabilir X ve Y koordinatları oluşturur.
Bir sonraki adımda, birden fazla KeyPosition kullanarak daha da karmaşık yollar oluşturmayı öğreneceksiniz.
7. Karmaşık yollar oluşturma
Son adımda oluşturduğunuz animasyona baktığımızda, düzgün bir eğri oluşturduğunu ancak şeklin daha "ay benzeri" olabileceğini görüyoruz.
Birden fazla KeyPosition öğesi içeren bir yolu değiştirme
MotionLayout, herhangi bir hareketi elde etmek için gereken sayıda KeyPosition tanımlayarak yolu daha da değiştirebilir. Bu animasyonda bir yay oluşturacaksınız ancak isterseniz ayı ekranın ortasında yukarı ve aşağı zıplatabilirsiniz.
xml/step4.xmladlı kişiyi aç. Son adımda eklediğiniz görüntülemelerin veKeyFramesayısının aynı olduğunu görürsünüz.- Eğrinin üst kısmını tamamlamak için
@id/moonyoluna iki tane dahaKeyPositionsekleyin. Bunlardan biri tepeye ulaşmadan hemen önce, diğeri ise ulaştıktan sonra olmalıdır.

step4.xml
<!-- TODO: Add two more KeyPositions to the KeyFrameSet here -->
<KeyPosition
motion:framePosition="25"
motion:motionTarget="@id/moon"
motion:keyPositionType="parentRelative"
motion:percentY="0.6"
/>
<KeyPosition
motion:framePosition="75"
motion:motionTarget="@id/moon"
motion:keyPositionType="parentRelative"
motion:percentY="0.6"
/>
Bu KeyPositions, animasyonun% 25 ve% 75'i tamamlandığında uygulanır ve @id/moon öğesinin ekranın üst kısmından% 60 uzaklıkta bir yolda hareket etmesine neden olur. %50'lik mevcut KeyPosition ile birleştiğinde, ayın izleyeceği düzgün bir yay oluşturur.
MotionLayout bölümünde, istediğiniz hareket yolunu elde etmek için ihtiyacınız olan sayıda KeyPositions ekleyebilirsiniz. MotionLayout, belirtilen framePosition'de her bir KeyPosition'i uygular ve tüm KeyPositions'den geçen akıcı bir hareketin nasıl oluşturulacağını belirler.
Deneyin
- Uygulamayı tekrar çalıştırın. Animasyonun işleyiş şeklini görmek için 4. Adım'a gidin. Ayı tıkladığınızda,
KeyFrameSetiçinde belirtilen her birKeyPositionöğesinden geçerek baştan sona kadar yolu takip eder.
Kendiniz keşfedin
Diğer KeyFrame türlerine geçmeden önce, yalnızca KeyPosition kullanarak ne tür efektler oluşturabileceğinizi görmek için KeyFrameSet'ye biraz daha KeyPositions eklemeyi deneyin.
Aşağıda, animasyon sırasında ileri geri hareket eden karmaşık bir yolun nasıl oluşturulacağını gösteren bir örnek verilmiştir.

step4.xml
<!-- Complex paths example: Dancing moon -->
<KeyFrameSet>
<KeyPosition
motion:framePosition="25"
motion:motionTarget="@id/moon"
motion:keyPositionType="parentRelative"
motion:percentY="0.6"
motion:percentX="0.1"
/>
<KeyPosition
motion:framePosition="50"
motion:motionTarget="@id/moon"
motion:keyPositionType="parentRelative"
motion:percentY="0.5"
motion:percentX="0.3"
/>
<KeyPosition
motion:framePosition="75"
motion:motionTarget="@id/moon"
motion:keyPositionType="parentRelative"
motion:percentY="0.6"
motion:percentX="0.1"
/>
</KeyFrameSet>
KeyPosition keşfini tamamladığınızda sonraki adımda diğer KeyFrames türlerine geçeceksiniz.
8. Hareket sırasında özellikleri değiştirme
Dinamik animasyonlar oluşturmak genellikle animasyon ilerledikçe görünümlerin size, rotation veya alpha özelliklerini değiştirmek anlamına gelir. MotionLayout, KeyAttribute kullanarak herhangi bir görünümde birçok özelliğin canlandırılmasını destekler.
Bu adımda, Ay'ın ölçeğini ayarlamak ve döndürmek için KeyAttribute simgesini kullanacaksınız. Metnin görünümünü, ay yolculuğunu neredeyse tamamlayana kadar geciktirmek için de KeyAttribute kullanacaksınız.
1. adım: KeyAttribute ile yeniden boyutlandırın ve döndürün
- Son adımda oluşturduğunuz animasyonu içeren
xml/step5.xmldosyasını açın. Bu ekranda, çeşitlilik için arka plan olarak farklı bir uzay resmi kullanılıyor. - Ayın boyutunu büyütmek ve döndürmek için
KeyAttributeetiketleriniKeyFrameSetbölümünekeyFrame="50"vekeyFrame="100"konumlarında ekleyin.

step5.xml
<!-- TODO: Add KeyAttributes to rotate and resize @id/moon -->
<KeyAttribute
motion:framePosition="50"
motion:motionTarget="@id/moon"
android:scaleY="2.0"
android:scaleX="2.0"
android:rotation="-360"
/>
<KeyAttribute
motion:framePosition="100"
motion:motionTarget="@id/moon"
android:rotation="-720"
/>
Bu KeyAttributes, animasyonun% 50'si ve% 100'ü için uygulanır. %50'deki ilk KeyAttribute, yayın eğrisinin en üstünde gerçekleşir ve görünümün hem iki kat büyümesine hem de -360 derece (veya tam bir daire) dönmesine neden olur. İkinci KeyAttribute, ikinci dönüşü -720 dereceye (iki tam daire) tamamlayacak ve scaleX ile scaleY değerleri varsayılan olarak 1,0 olduğundan boyutu tekrar normal boyutuna küçültecektir.
KeyPosition gibi, KeyAttribute de KeyFrame'nin ne zaman uygulanacağını ve hangi görünümün değiştirileceğini belirtmek için framePosition ve motionTarget'ü kullanır. Akıcı animasyonlar oluşturmak için MotionLayout ile KeyPositions arasında enterpolasyon yapılır.
KeyAttributes Tüm görünümlere uygulanabilen özellikleri destekler. visibility, alpha veya elevation gibi temel özelliklerin değiştirilmesini destekler. Ayrıca, döndürmeyi burada yaptığınız gibi değiştirebilir, rotateX ve rotateY ile üç boyutta döndürebilir, scaleX ve scaleY ile boyutu ölçeklendirebilir veya görünümün konumunu X, Y ya da Z ekseninde çevirebilirsiniz.
2. adım: Jeneriklerin görünümünü geciktirin
Bu adımın amaçlarından biri, animasyonu güncelleyerek animasyon neredeyse tamamlanana kadar jenerik metninin görünmemesini sağlamaktır.
- Kredilerin görünümünü geciktirmek için
KeyAttributedeğerini,alphadeğerininkeyPosition="85"değerine kadar 0 kalmasını sağlayacak şekilde tanımlayın.MotionLayout, 0'dan 100 alfa değerine sorunsuz bir şekilde geçiş yapmaya devam eder ancak bunu animasyonun son% 15'inde yapar.
step5.xml
<!-- TODO: Add KeyAttribute to delay the appearance of @id/credits -->
<KeyAttribute
motion:framePosition="85"
motion:motionTarget="@id/credits"
android:alpha="0.0"
/>
Bu KeyAttribute, animasyonun ilk% 85'i boyunca @id/credits alpha değerini 0,0'da tutar. Alfa değeri 0'dan başladığı için animasyonun ilk% 85'inde görünmez olur.
Bu KeyAttribute işleminin sonucunda, animasyonun sonuna doğru krediler gösterilir. Bu sayede, ekranın sağ köşesinde yerleşen ay ile uyumlu bir görünüm elde edilir.
Bir görünüm bu şekilde hareket ederken başka bir görünümdeki animasyonları geciktirerek kullanıcıya dinamik hissettiren etkileyici animasyonlar oluşturabilirsiniz.
Deneyin
- Uygulamayı tekrar çalıştırın ve animasyonu çalışırken görmek için 5. adıma gidin. Ayı tıkladığınızda,
KeyFrameSetiçinde belirtilen herKeyAttribute'dan geçerek baştan sona kadar yolu takip eder.

Ayı iki tam daire döndürdüğünüz için artık iki kez geriye doğru takla atacak ve animasyon neredeyse tamamlanana kadar jenerik gösterilmeyecek.
Kendiniz keşfedin
Son KeyFrame türüne geçmeden önce KeyAttributes içindeki diğer standart özellikleri değiştirmeyi deneyin. Örneğin, hangi animasyonun oluşturulduğunu görmek için rotation simgesini rotationX olarak değiştirmeyi deneyin.
Aşağıda, deneyebileceğiniz standart özelliklerin listesi verilmiştir:
android:visibilityandroid:alphaandroid:elevationandroid:rotationandroid:rotationXandroid:rotationYandroid:scaleXandroid:scaleYandroid:translationXandroid:translationYandroid:translationZ
9. Özel özellikleri değiştirme
Zengin animasyonlar, bir görünümün rengini veya diğer özelliklerini değiştirmeyi içerir. MotionLayout, önceki görevde listelenen standart özelliklerden herhangi birini değiştirmek için KeyAttribute kullanabilirken diğer özellikleri belirtmek için CustomAttribute kullanırsınız.
CustomAttribute, ayarlayıcısı olan herhangi bir değeri ayarlamak için kullanılabilir. Örneğin, CustomAttribute kullanarak bir Görünüm'de backgroundColor'ı ayarlayabilirsiniz. MotionLayout, belirleyiciyi bulmak için yansıtmayı kullanır, ardından görünümü canlandırmak için belirleyiciyi tekrar tekrar çağırır.
Bu adımda, aşağıdaki animasyonu oluşturmak için ay üzerindeki colorFilter özelliğini ayarlamak üzere CustomAttribute kullanacaksınız.

Özel özellikler tanımlama
- Başlamak için son adımda oluşturduğunuz animasyonu içeren
xml/step6.xmldosyasını açın. - Ayın renk değiştirmesini sağlamak için
KeyAttributesimgesiniKeyFrameSetbölümünekeyFrame="0",keyFrame="50"vekeyFrame="100".konumlarındaCustomAttributeile birlikte ekleyin.

step6.xml
<!-- TODO: Add Custom attributes here -->
<KeyAttribute
motion:framePosition="0"
motion:motionTarget="@id/moon">
<CustomAttribute
motion:attributeName="colorFilter"
motion:customColorValue="#FFFFFF"
/>
</KeyAttribute>
<KeyAttribute
motion:framePosition="50"
motion:motionTarget="@id/moon">
<CustomAttribute
motion:attributeName="colorFilter"
motion:customColorValue="#FFB612"
/>
</KeyAttribute>
<KeyAttribute
motion:framePosition="100"
motion:motionTarget="@id/moon">
<CustomAttribute
motion:attributeName="colorFilter"
motion:customColorValue="#FFFFFF"
/>
</KeyAttribute>
KeyAttribute içine CustomAttribute eklediğinizde CustomAttribute, KeyAttribute tarafından belirtilen framePosition tarihinde uygulanır.
CustomAttribute içinde bir attributeName ve ayarlanacak bir değer belirtmeniz gerekir.
motion:attributeName, bu özel özellik tarafından çağrılacak ayarlayıcının adıdır. Bu örnekte,DrawableüzerindekisetColorFilterçağrılır.motion:custom*Value, adında belirtilen türde bir özel değerdir. Bu örnekte özel değer, belirtilen bir renktir.
Özel değerler aşağıdaki türlerden herhangi birine sahip olabilir:
- Renk
- Tamsayı
- Kayan
- Dize
- Boyut
- Boole
Bu API'yi kullanarak MotionLayout, herhangi bir görünümde ayarlayıcı sağlayan her şeyi canlandırabilir.
Deneyin
- Uygulamayı tekrar çalıştırın ve animasyonu çalışırken görmek için 6. adıma gidin. Ayı tıkladığınızda,
KeyFrameSetiçinde belirtilen herKeyAttribute'dan geçerek baştan sona kadar yolu takip eder.

Daha fazla KeyFrames eklediğinizde MotionLayout, ayın yolunu düz bir çizgiden karmaşık bir eğriye dönüştürür. Animasyonun ortasında çift geri takla, yeniden boyutlandırma ve renk değişikliği eklenir.
Gerçek animasyonlarda genellikle birden fazla görünümü aynı anda canlandırır, hareketlerini farklı yollar ve hızlarda kontrol edersiniz. Her görünüm için farklı bir KeyFrame belirterek, MotionLayout ile birden fazla görünümü canlandıran zengin animasyonlar oluşturmak mümkündür.
10. Etkinlikleri ve karmaşık yolları sürükleme
Bu adımda, karmaşık yollarla OnSwipe kullanmayı keşfedeceksiniz. Şimdiye kadar ayın animasyonu bir OnClick dinleyicisi tarafından tetikleniyordu ve sabit bir süre boyunca çalışıyordu.
Son birkaç adımda oluşturduğunuz ay animasyonu gibi OnSwipe ile karmaşık yollara sahip animasyonları kontrol etmek için OnSwipe'nın nasıl çalıştığını anlamanız gerekir.
1. adım: OnSwipe davranışını keşfedin
xml/step7.xmlsimgesini açın ve mevcutOnSwipebeyanını bulun.
step7.xml
<!-- Fix OnSwipe by changing touchAnchorSide →
<OnSwipe
motion:touchAnchorId="@id/moon"
motion:touchAnchorSide="bottom"
/>
- Uygulamayı cihazınızda çalıştırın ve 7. adım'a gidin. Ayı yayın yolu boyunca sürükleyerek akıcı bir animasyon oluşturup oluşturamayacağınızı görün.
Bu animasyonu çalıştırdığınızda çok iyi görünmüyor. Ay, yayın en üst noktasına ulaştıktan sonra etrafta zıplamaya başlar.

Hatayı anlamak için kullanıcının yayın üst kısmının hemen altına dokunduğunda ne olduğunu düşünün. OnSwipe etiketi motion:touchAnchorSide="bottom" içerdiğinden MotionLayout, animasyon boyunca parmak ile görünümün alt kısmı arasındaki mesafeyi sabit tutmaya çalışır.
Ancak ayın alt kısmı her zaman aynı yönde hareket etmediği için (önce yukarı çıkar, sonra tekrar aşağı iner) MotionLayout, kullanıcı yayın en üst noktasını geçtiğinde ne yapacağını bilemez. Bunu göz önünde bulundurmak için, ayın alt kısmını izlediğinize göre kullanıcı buraya dokunduğunda nereye yerleştirilmelidir?

2. adım: Doğru tarafı kullanın
Bu tür hataları önlemek için animasyonun tamamı boyunca her zaman tek bir yönde ilerleyen bir touchAnchorId ve touchAnchorSide seçmek önemlidir.
Bu animasyonda, Ay'ın hem right tarafı hem de left tarafı ekranda tek bir yönde ilerler.
Ancak hem bottom hem de top ters yönde hareket eder. OnSwipe onları izlemeye çalıştığında yönleri değiştiğinde kafası karışır.
- Bu animasyonun dokunma etkinliklerini takip etmesini sağlamak için
touchAnchorSidedeğerinirightolarak değiştirin.
step7.xml
<!-- Fix OnSwipe by changing touchAnchorSide →
<OnSwipe
motion:touchAnchorId="@id/moon"
motion:touchAnchorSide="right"
/>
3. adım: dragDirection'ı kullanın
Ayrıca, bir yan parçanın normalde olduğundan farklı bir yönde ilerlemesini sağlamak için dragDirection ile touchAnchorSide simgesini birleştirebilirsiniz. touchAnchorSide öğesinin yalnızca tek bir yönde ilerlemesi önemlidir ancak touchAnchorSide öğesine hangi yönde izleneceğini söyleyebilirsiniz.MotionLayout Örneğin, touchAnchorSide="bottom" simgesini koruyup dragDirection="dragRight" simgesini ekleyebilirsiniz. Bu durumda MotionLayout, görünümün alt kısmının konumunu izler ancak yalnızca sağa hareket ederken konumunu dikkate alır (dikey hareketi yoksayar). Bu nedenle, alt kısım yukarı ve aşağı hareket etse de OnSwipe ile doğru şekilde animasyon oluşturulur.
- Ayın hareketini doğru şekilde takip etmek için
OnSwipeuygulamasını güncelleyin.
step7.xml
<!-- Using dragDirection to control the direction of drag tracking →
<OnSwipe
motion:touchAnchorId="@id/moon"
motion:touchAnchorSide="bottom"
motion:dragDirection="dragRight"
/>
Deneyin
- Uygulamayı tekrar çalıştırın ve ayı tüm yol boyunca sürüklemeyi deneyin. Karmaşık bir yay izlese de
MotionLayout, kaydırma etkinliklerine yanıt olarak animasyonu ilerletebilir.

11. Kodu kullanarak hareket çalıştırma
MotionLayout, CoordinatorLayout ile birlikte kullanıldığında zengin animasyonlar oluşturmak için kullanılabilir. Bu adımda, MotionLayout kullanarak daraltılabilir bir başlık oluşturacaksınız.
1. adım: Mevcut kodu inceleyin
- Başlamak için
layout/activity_step8.xmluygulamasını açın. layout/activity_step8.xmliçinde, çalışan birCoordinatorLayoutveAppBarLayout'nin zaten oluşturulduğunu görürsünüz.
activity_step8.xml
<androidx.coordinatorlayout.widget.CoordinatorLayout
...>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar_layout"
android:layout_width="match_parent"
android:layout_height="180dp">
<androidx.constraintlayout.motion.widget.MotionLayout
android:id="@+id/motion_layout"
... >
...
</androidx.constraintlayout.motion.widget.MotionLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
...
motion:layout_behavior="@string/appbar_scrolling_view_behavior" >
...
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Bu düzen, NestedScrollView ile AppBarLayout arasında kaydırma bilgilerini paylaşmak için CoordinatorLayout kullanır. Bu nedenle, NestedScrollView yukarı kaydığında AppBarLayout'ye değişiklik hakkında bilgi verir. Android'de bu tür daraltılabilir araç çubuğu bu şekilde uygulanır. Metnin kaydırılması, daraltılabilir üstbilgiyle "koordine edilir".
@id/motion_layout ile gösterilen hareket sahnesi, son adımdaki hareket sahnesine benzer. Ancak OnSwipe ile çalışabilmesi için OnSwipe bildirimi kaldırıldı.CoordinatorLayout
- Uygulamayı çalıştırın ve 8. adıma gidin. Metni kaydırdığınızda ayın hareket etmediğini görürsünüz.
2. adım: MotionLayout'un kaydırılmasını sağlama
NestedScrollViewkaydırılır kaydırılmazMotionLayoutgörünümünün de kaydırılması içinMotionLayout'yamotion:minHeightvemotion:layout_scrollFlagsekleyin.
activity_step8.xml
<!-- Add minHeight and layout_scrollFlags to the MotionLayout -->
<androidx.constraintlayout.motion.widget.MotionLayout
android:id="@+id/motion_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
motion:layoutDescription="@xml/step8"
motion:motionDebug="SHOW_PATH"
android:minHeight="80dp"
motion:layout_scrollFlags="scroll|enterAlways|snap|exitUntilCollapsed" >
- Uygulamayı tekrar çalıştırın ve 8. adıma gidin. Yukarı kaydırdığınızda
MotionLayoutsimgesinin daraldığını görürsünüz. Ancak animasyon henüz kaydırma davranışına göre ilerlemiyor.
3. adım: Hareketi kodla taşıyın
Step8Activity.ktuygulamasını açın . Kaydırma konumundaki değişiklikleriMotionLayout'a bildirmek içincoordinateMotion()işlevini düzenleyin.
Step8Activity.kt
// TODO: set progress of MotionLayout based on an AppBarLayout.OnOffsetChangedListener
private fun coordinateMotion() {
val appBarLayout: AppBarLayout = findViewById(R.id.appbar_layout)
val motionLayout: MotionLayout = findViewById(R.id.motion_layout)
val listener = AppBarLayout.OnOffsetChangedListener { unused, verticalOffset ->
val seekPosition = -verticalOffset / appBarLayout.totalScrollRange.toFloat()
motionLayout.progress = seekPosition
}
appBarLayout.addOnOffsetChangedListener(listener)
}
Bu kod, kullanıcının geçerli kaydırma uzaklığıyla her kaydırma işleminde çağrılacak bir OnOffsetChangedListener kaydeder.
MotionLayout, ilerleme özelliğini ayarlayarak geçişi destekler. verticalOffset ile ilerleme yüzdesi arasında dönüşüm yapmak için toplam kaydırma aralığına bölün.
Deneyin
- Uygulamayı tekrar dağıtın ve 8. Adım animasyonunu çalıştırın.
MotionLayoutsimgesinin, kaydırma konumuna göre animasyonu ilerlettiğini görürsünüz.

MotionLayout kullanarak özel dinamik daraltılabilir araç çubuğu animasyonları oluşturabilirsiniz. KeyFrames dizisi kullanarak çok çarpıcı efektler elde edebilirsiniz.
12. Tebrikler
Bu kod laboratuvarında MotionLayout'nın temel API'si ele alınmıştır.
MotionLayout'nın uygulamadaki diğer örneklerini görmek için resmi örneğe göz atın. Ayrıca belgelere göz atmayı unutmayın.
Daha Fazla Bilgi
MotionLayout, bu kod laboratuvarında ele alınmayan daha da fazla özelliği destekler. Örneğin, KeyCycle, ile yolları veya özellikleri tekrarlayan döngülerle kontrol edebilir, KeyTimeCycle, ile de saat zamanına göre animasyon oluşturabilirsiniz. Her birinin örnekleri için numunelere göz atın.
Bu kurstaki diğer codelab'lerin bağlantıları için Kotlin'de İleri Düzey Android codelab'leri açılış sayfasına bakın.