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ıralı bir şekilde uygulamanız gerekir. Ancak bu zorunlu değildir. Tüm kurs codelab'leri Gelişmiş Android in Kotlin codelab'leri açılış sayfasında listelenmiştir.
MotionLayout, Android uygulamanıza rich motion eklemenizi sağlayan bir kitaplıktır. ConstraintLayout, öğesini temel alır ve ConstraintLayout ile oluşturabileceğiniz her şeyi canlandırmanızı sağlar.
Birden fazla görünümün konum, boyut, görünürlük, alfa, renk, yükseklik, döndürme ve diğer özelliklerine aynı anda animasyon eklemek için MotionLayout öğesini kullanabilirsiniz. Bildirim temelli XML kullanarak, kodda ulaşılması zor olan birden çok görünüm içeren koordine animasyonlar oluşturabilirsiniz.
Animasyonlar, uygulama deneyimini geliştirmenin mükemmel bir yoludur. Animasyonları kullanarak şunları yapabilirsiniz:
- Değişiklikleri göster: Durumlar arasında animasyon oluşturmak, kullanıcının kullanıcı arayüzündeki değişiklikleri doğal olarak izlemesini sağlar.
- Dikkat çekin: Önemli kullanıcı arayüzü öğelerine dikkat çekmek için animasyonlar kullanın.
- Güzel tasarımlar oluşturun: Tasarımda etkili hareketler olması uygulamaların şık görünmesini sağlar.
Ön koşullar
Bu codelab, Android geliştirme deneyimi olan geliştiriciler için tasarlanmıştır. Bu codelab'i tamamlamaya çalışmadan önce şunları yapmalısınız:
- Etkinlik ve temel düzen içeren bir uygulama oluşturmayı ve Android Studio'yu kullanarak uygulamayı bir cihazda ya da emülatörde çalıştırmayı öğrenme.
ConstraintLayouthakkında bilgi edinin.ConstraintLayouthakkında daha fazla bilgi edinmek için Kısıtlama Düzeni codelab'ini okuyun.
Yapacaklarınız
ConstraintSetsveMotionLayoutile animasyon tanımlayın- Sürükleme etkinliklerine göre animasyon uygulama
- Animasyonu
KeyPositionile değiştirin - Özellikleri
KeyAttributeile değiştirin - Animasyonları kodla çalıştırma
- Daraltılabilir başlıkları
MotionLayoutile canlandırın
Gerekenler
- Android Studio 4.0 (
MotionLayoutdüzenleyicisi yalnızca Android Studio'nun bu 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ı tıklamalarına yanıt olarak görünümü ekranın üst kısmından en alt uca taşıyan bir animasyon oluşturacaksınız.
Başlangıç kodundan animasyon oluşturmak için aşağıdaki ana parçalara ihtiyacınız vardır:
ConstraintLayoutalt sınıfı olan birMotionLayout,. Animasyonlu olacak tüm görünümleriMotionLayoutetiketinin içinde belirtirsiniz.MotionLayout.için bir animasyonu açıklayan XML dosyası olanMotionScene,- Animasyon süresini, tetikleyiciyi ve görünümlerin nasıl taşınacağını belirten,
MotionSceneöğesinin parçası olan birTransition,. - Geçişin hem start hem de end kısıtlamalarını belirten bir
ConstraintSet.
MotionLayout ile başlayarak sırasıyla bunların her birine göz atalım.
1. Adım: Mevcut kodu inceleyin
MotionLayout, ConstraintLayout etiketinin alt sınıfıdır. Bu nedenle, animasyon eklerken aynı özellikleri destekler. MotionLayout özelliğini kullanmak için ConstraintLayout. kullanacağınız bir MotionLayout görünümü ekleyin
res/layoutiçindeactivity_step1.xml.uygulamasını açın. Burada, içinde tek birImageViewyıldız bulunan ve içinde ton uygulanmış birConstraintLayoutvar.
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 cihazda herhangi bir kısıtlama yoktur. Bu nedenle, uygulamayı şimdi çalıştırırsanız yıldız ekranı kısıtlanmamış olarak gösterilir. Bu durum, öğelerin bilinmeyen bir konumda yer alacağı anlamına gelir. Android Studio, kısıtlama olmadığında size uyarı gönderir.
2. Adım: Hareket Düzeni'ne dönüştürün
MotionLayout, kullanarak animasyon eklemek için ConstraintLayout öğesini MotionLayout biçimine dönüştürmeniz gerekir.
Düzeninizin bir hareket sahnesini kullanabilmesi için 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 MotionLayout'a Dönüştür seçeneğini belirleyin.

Bu işlem, ConstraintLayout etiketini MotionLayout etiketiyle değiştirir ve MotionLayout etiketine, @xml/activity_step1_scene. öğesine 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 dönüştürdüğünüzde tasarım yüzeyinde Hareket Düzenleyici gösterilir

Hareket Düzenleyici'de üç yeni kullanıcı arayüzü öğesi var:
- Genel Bakış: Bu, animasyonun farklı bölümlerini seçmenize olanak tanıyan bir kalıcı 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, o sırada 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çili olan geçerli öğenin özelliklerini gösterir ve düzenlemenize olanak tanır. Bu resimde,
startConstraintSetözellikleri gösterilmektedir.
3. adım: Başlangıç ve bitiş kısıtlamalarını tanımlayın
Tüm animasyonlar bir başlangıç ve bitiş olarak tanımlanabilir. Başlangıç, animasyondan önceki ekranın, sonda ise animasyon tamamlandıktan sonra ekranın nasıl görüneceğiyle açıklanır. MotionLayout, başlangıç ve bitiş durumları arasında (zaman içinde) nasıl animasyon yapılacağını belirlemekten sorumludur.
MotionScene, başlangıç ve bitiş durumlarını tanımlamak için bir ConstraintSet etiketi kullanır. ConstraintSet, görünümlere uygulanabilecek bir dizi kısıtlamadır. Buna genişlik, yükseklik ve ConstraintLayout kısıtlamaları dahildir. Ayrıca alpha gibi bazı özellikler de içerir. Bu rapor, görünümlerin kendisini içermez, yalnızca bu görünümlerdeki kısıtlamaları içerir.
ConstraintSet öğesinde belirtilen kısıtlamalar, düzen dosyasında belirtilen kısıtlamaları geçersiz kılar. Hem düzende hem de MotionScene öğesinde kısıtlamalar tanımlarsanız yalnızca MotionScene öğesindeki kısıtlamalar uygulanır.
Bu adımda, yıldız görünümünü ekranın üst başlangıcında başlayıp alt ucunda bitecek şekilde sınırlandırırsınız.
Bu adımı Hareket Düzenleyici'yi 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, değerin buConstraintSetiçinde kısıtlanmadığı anlamına gelir. Kısıtlama Oluşturma için sağ üstteki kalem simgesini kullanın.

- Genel bakış panelinde
startConstraintSetseçildiğinde,red_staröğesininstartKaynağını gösterdiğini onaylayın. - Özellikler panelinde,
startConstraintSetiçindered_starseçiliyken en üst kısma bir Sınırlama ekleyin ve mavi + düğmelerini tıklayarak başlayın.

- Hareket Düzenleyici'nin bu kısıtlama için oluşturduğu kodu görmek için
xml/activity_step1_scene.xmldosyasını 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 değerine sahip @id/start 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 öğesine ihtiyaç duyuyor.
ConstraintSet içindeki Constraint, kısıtladığı görünümün kimliğini belirtir (@id/red_star activity_step1.xml içinde tanımlanır). Constraint etiketlerinin yalnızca kısıtlamaları ve düzen bilgilerini belirttiğini unutmayın. Constraint etiketi, bir ImageView öğesine uygulandığını bilmez.
Bu kısıtlama, red_star görünümünü üst öğesinin üst başlangıcıyla sınırlamak 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 üzere Hareket Düzenleyici'yi kullanmak için mavi + düğmelerini tıklayarak
bottomveendiçin bir kısıtlama ekleyin.

- XML'deki kod aşağıdaki gibi 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 için de @id/red_star üzerinde tek bir Constraint var. Bu kez simge, ekranın alt ucuyla sınırlandırılıyor.
Bu öğeleri @id/start ve @id/end olarak adlandırmanıza gerek yoktur ancak kolaylık sağlar.
4. Adım: Bir geçiş tanımlayın
Her MotionScene en az bir geçiş içermelidir. Geçiş, bir animasyonun başından sonuna her bölümünü tanımlar.
Geçişin, geçiş için bir başlangıç ve bitiş ConstraintSet belirtmesi gerekir. Geçiş, animasyonun ne kadar süreyle çalıştırılacağını veya görünümleri sürükleyerek animasyonun nasıl düzenleneceğini gibi diğer şekillerde nasıl değiştirileceğini de belirtebilir.
- MotionScene dosyası oluşturulurken Hareket Düzenleyici varsayılan olarak bizim için bir geçiş oluşturdu. Oluşturulan geçişi görmek için
activity_step1_scene.xmluygulamasını 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 uygulamasının animasyon oluşturmak için ihtiyaç duyduğu tüm bilgiler bunlar. Özelliklere göz atarak:
- Animasyon başladığında görünümlere
constraintSetStartuygulanır. constraintSetEnd, animasyonun sonundaki görünümlere uygulanır.duration, animasyonun ne kadar süreceğini belirtir.
Ardından MotionLayout, başlangıç ve bitiş kısıtlamaları arasında bir yol belirler ve belirtilen süre boyunca bu kısıtlamaları canlandırır.
5. Adım: Hareket Düzenleyici'de animasyonu önizleyin

Animasyon: Hareket Düzenleyici'de geçiş önizlemesi oynatma videosu
- Hareket Düzenleyici'yi açın ve genel bakış panelinde
startileendarasındaki oku tıklayarak geçişi seçin.

- Seçim panelinde, bir geçiş seçildiğinde oynatma kontrolleri ve bir ileri geri çubuğu gösterilir. Animasyonu önizlemek için oynat'ı tıklayın veya geçerli konumu sürükleyin.

6. Adım: Tıklama işleyici ekleyin
Animasyonu başlatmak için bir yönteme ihtiyacınız var. 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ıç ve 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şleyici oluştur'u tıklayın . Bu işlem, geçiş başlatacak bir işleyici ekler. - Pop-up'tan Tıklama İşleyici'yi seçin.

- Tıklanacak Görünüm değerini
red_starolarak değiştirin.

- Ekle'yi tıklayın. Tıklama işleyici, Hareket Düzenleyici'de Geçiş için küçük bir noktayla gösterilir.

- Genel bakış panelinde geçiş seçiliyken, özellikler panelinde az önce eklediğiniz OnClick işleyiciye
toggleiçin birclickActionözelliği ekleyin.

- Hareket Düzenleyici'nin oluşturduğu kodu görmek için
activity_step1_scene.xmluygulamasını 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 uygulamasına, tıklama etkinliklerine yanıt olarak animasyonu <OnClick> etiketi kullanarak çalıştırmasını söyler. Özelliklere göz atarak:
targetId, tıklamalar için izlenecek görünümdür.toggleöğesininclickActionkadarı, tıklandığında başlangıç ve bitiş durumu arasında geçiş yapacak.clickActionile ilgili diğer seçenekleri belgelerde bulabilirsiniz.
- Kodunuzu çalıştırın, 1. Adım'ı ve ardından kırmızı yıldızı tıklayın ve animasyonu görün!
5. Adım: Animasyonların işleyiş şekli
Uygulamayı çalıştırın. Yıldızı tıkladığınızda animasyonunuzun çalıştığını görürsünüz.

Tamamlanan hareket sahnesi dosyası, ConstraintSet başlangıç ve bitişine işaret eden bir Transition tanımlar.
Animasyonun başında (@id/start) yıldız simgesi, ekranın üst başlangıcıyla sınırlandırılır. Animasyonun sonunda (@id/end) yıldız simgesi ekranın alt ucuyla sınırlanır.
<?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 dayalı animasyon
Bu adım için, animasyonu çalıştırmak üzere kullanıcı 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 hareket ettirmek için dokunma etkinliklerini takip etmenin yanı sıra hareketi daha akıcı hale getirmek için fiziğe dayalı hızlıca kaydırma hareketlerini destekler.
1. Adım: İlk kodu inceleyin
- Başlamak için mevcut
MotionLayoutöğesine sahipactivity_step2.xmldüzen dosyasını açı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, animasyona ilişkin tüm görünümleri tanımlar. Üç yıldız simgeleri, hareket sahnesinde canlandırılacağı için düzende kısıtlı değildir.
TextView kredilerine kısıtlamalar uygulandığından tüm animasyon boyunca aynı yerde kaldığı ve hiçbir özelliği değiştirmediği için bu kredilere kısıtlamalar uygulanmıştır.
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.
ConstraintSet başlangıcını tanımlayın
- Animasyonu tanımlamak için
xml/step2.xmlhareket sahnesini açın. startbaşlangıç kısıtlaması için kısıtlamaları ekleyin. Başlangıçta, üç yıldız da ekranın alt kısmında ortalanır. Sağ ve sol yıldızlar,0.0olanalphadeğerine sahiptir. Bu, tamamen şeffaf ve gizli oldukları 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 bir 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 sınırlamalar kullanılarak ekranın alt kısmına ortalanır. @id/left_star ve @id/right_star adlı iki yıldız, onları görünmez hale getiren ve animasyonun başında uygulanacak ek bir alfa değerine sahiptir.
start ve end kısıtlama grupları, animasyonun başlangıcını ve bitişini tanımlar. Başlangıçtaki motion:layout_constraintStart_toStartOf gibi bir sınırlama, 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. Bu durum başta kafa karıştırıcı olabilir çünkü start adı hem hem kısıtlamalar bağlamında kullanılır. Ayrımı ortaya çıkarmaya yardımcı olması açısından, layout_constraintStart içindeki start, "başlangıç" anlamına gelir soldan sağa dilde ve sağdan sola yazılan bir dilde sağdan sola görünümün bulunduğu görünümü içerir. start kısıtlaması ayarı, animasyonun başlangıcını ifade eder.
End ConstraintSet'i tanımlayın
- Üç yıldızın tümünü
@id/creditsaltında birlikte konumlandırmak amacıyla zincir kullanmak için son kısıtlamayı tanımlayın. Buna ek olarak, sol ve sağ yıldızlarınalphabitiş değeri1.0olarak ayarlanır.
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 görünümler, hareket ettikçe merkeze doğru yayılır ve yukarıya doğru gider.
Buna ek olarak, alpha özelliği hem ConstraintSets içinde @id/right_start hem de @id/left_star üzerinde ayarlandığından, animasyon ilerledikçe her iki görünüm de azalır.
Kullanıcının kaydırmasına göre animasyon
MotionLayout, fiziğe dayalı bir "hızlı hareket" oluşturmak için kullanıcının sürükleme etkinliklerini veya kaydırma işlemlerini izleyebilir animasyon ekler. Diğer bir deyişle, kullanıcı tarafından sallanan görünümler devam edecek ve fiziksel bir nesnenin yuvarlandığı gibi yavaşlayacaktır. Bu animasyon türünü Transition içindeki bir OnSwipe etiketiyle ekleyebilirsiniz.
OnSwipeetiketini<OnSwipe motion:touchAnchorId="@id/red_star" />ile eklemek için YAPILACAKLAR kısmını 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çeriyor. Bunlardan en önemlisi touchAnchorId.
touchAnchorId, dokunmaya yanıt olarak hareket eden izlenen görünümdür.MotionLayout, bu görünümü kaydıran parmakla aynı mesafede tutar.touchAnchorSide, görünümün hangi tarafının izlenmesi gerektiğini belirler. Bu, yeniden boyutlandırılan, karmaşık yolları takip eden veya bir tarafı diğerine göre daha hızlı hareket eden görünümler için önemlidir.dragDirection, bu animasyon için hangi yönün (yukarı, aşağı, sol veya sağ) önemli olduğunu belirler.
MotionLayout, sürükleme etkinliklerini dinlediğinde, işleyici touchAnchorId tarafından belirtilen görünüme değil, MotionLayout görünümüne kaydedilir. Kullanıcı ekranın herhangi bir yerinde bir hareketi başlattığında MotionLayout, parmağı ile touchAnchorId görünümünün touchAnchorSide arasındaki mesafeyi sabit tutar. Örneğin, sabit taraftan 100 dp uzaklığa dokunursa MotionLayout, animasyonun tamamı 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.
- "Hızlıca kaydırma"yı deneyin veya
MotionLayoutöğesinin, akışkan fiziğe dayalı animasyonları nasıl görüntülediğini keşfetmek için parmağınızı animasyonun ortasında bırakın.

MotionLayout, zengin efektler oluşturmak için ConstraintLayout özelliklerini kullanarak çok farklı tasarımlar arasında animasyon oluşturabilir.
Bu animasyonda, üç görünüm de başlamak için ekranın alt kısmındaki üst öğelerine göre konumlandırılır. Sonda, üç görünüm bir zincirdeki @id/credits öğesine göre konumlandırılır.
Bu çok farklı düzenlere rağmen MotionLayout, başlangıç ve bitiş arasında değişken bir animasyon oluşturur.
5. Yolu değiştirme
Bu adımda, animasyon sırasında karmaşık bir yolu izleyen ve hareket sırasında jenerikleri animasyonla gösteren bir animasyon oluşturacaksınız. MotionLayout, görünümün başlangıç ve bitiş arasında izleyeceği yolu KeyPosition kullanarak 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öğelerini açın.ImageViewveTextViewsimgelerinde ay ve jenerik metni yer alıyor. - Hareket sahnesi dosyasını (
xml/step3.xml) açın.@id/startile@id/endarasında birTransitiondeğerinin tanımlandığını görüyorsunuz. Animasyon, ikiConstraintSetsöğesini kullanarak ay resmini ekranın sol alt kısmından ekranın sağ alt kısmına taşır. Ay hareket ederkenalpha="0.0"ilealpha="1.0"arasında jenerik metni görünür ve görünür. - Uygulamayı şimdi çalıştırın ve 3. Adım'ı seçin. Ay'ı tıkladığınızda ayın başından sonuna kadar doğrusal bir yol (veya düz bir çizgi) izlediğini göreceksiniz.
2. Adım: Yol hata ayıklama özelliğini etkinleştirin
Ayın hareketine bir yay eklemeden önce MotionLayout bölümünde yol hata ayıklama özelliğini etkinleştirmeniz faydalı olur.
MotionLayout ile karmaşık animasyonlar geliştirilmesine yardımcı olmak için her görünümün animasyon yolunu çizebilirsiniz. Bu, animasyonunuzu görselleştirmek ve hareketin küçük ayrıntılarını hassas bir şekilde ayarlamak istediğinizde yararlı olur.
- Hata ayıklama yollarını etkinleştirmek için
layout/activity_step3.xmlöğesini açın veMotionLayoutetiketinemotion:motionDebug="SHOW_PATH"ekleyin.
activity_step3.xml
<!-- Add motion:motionDebug="SHOW_PATH" -->
<androidx.constraintlayout.motion.widget.MotionLayout
...
motion:motionDebug="SHOW_PATH" >
Yol hata ayıklama özelliğini etkinleştirdikten sonra uygulamayı tekrar çalıştırdığınızda tüm görünümlerin yollarını noktalı bir çizgiyle görselleştirilmiş olarak görürsünüz.

- Daireler bir görünümün başlangıç veya bitiş konumunu temsil eder.
- Çizgiler, bir görünümün yolunu temsil eder.
- Elmas, yolu değiştiren bir
KeyPositiontemsil eder.
Örneğin, bu animasyonda ortadaki daire, jenerik metninin konumudur.
3. Adım: Yolu değiştirin
MotionLayout içindeki tüm animasyonlar, animasyon başlamadan önce ve tamamlandıktan sonra ekranın nasıl görüneceğini tanımlayan bir başlangıç ve bitiş (ConstraintSet) ile tanımlanır. Varsayılan olarak MotionLayout, konumu değiştiren her görünümün başlangıç ve bitiş konumları arasında doğrusal bir yol (düz bir çizgi) çizer.
Bu örnekte ayın yayağı gibi karmaşık yollar oluşturmak için MotionLayout, bir görünümün başlangıç ve bitiş arasında izlediği yolu değiştirmek üzere bir KeyPosition kullanır.
xml/step3.xmlöğesini 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, bir Transition öğesinin alt öğesidir. Geçiş sırasında uygulanması gereken tüm KeyFrames öğelerini (ör. KeyPosition) içeren bir gruptur.
MotionLayout, ayın başlangıç ve bitişi arasındaki yolunu hesaplarken yolu, KeyFrameSet öğesinde belirtilen KeyPosition temel alınarak değiştirir. Uygulamayı tekrar çalıştırarak yolu nasıl değiştirdiğini görebilirsiniz.
KeyPosition, yolu nasıl değiştirdiğini açıklayan çeşitli özelliklere sahiptir. Bunların en önemlileri şunlardır:
framePosition, 0 ile 100 arasında bir sayıdır. BuKeyPositionöğesinin animasyonda ne zaman uygulanması gerektiğini tanımlar. 1, animasyondan% 1, 99 değeri animasyon aracılığıyla% 99'dur. Değer 50 ise bunu hemen ortaya uygularsınız.motionTarget, buKeyPositionöğesinin yolunu değiştirdiği görünümdür.- Bu
KeyPosition, yolukeyPositionTypeolarak değiştirir.parentRelative,pathRelativeveyadeltaRelativeolabilir (sonraki adımda açıklandığı gibi). percentX | percentY,framePositioniçin yolun ne kadar değiştirileceğini belirtir (0,0 ile 1,0 arasındaki değerlere, negatif değerlere ve 1'den büyük değerlere izin verilir).
Şöyle düşünebilirsiniz: "framePosition konumunu percentX veya percentY yolu keyPositionType tarafından belirlenen koordinatlara göre taşıyarak motionTarget yolunu değiştirin."
MotionLayout, varsayılan olarak yolun değiştirilmesiyle ortaya çıkan tüm köşeleri yuvarlar. Az önce oluşturduğunuz animasyona bakarsanız ayın eğimli bir yolu takip ettiğini görebilirsiniz. Çoğu animasyonda istediğiniz budur. Aksi takdirde, animasyonları özelleştirmek için curveFit özelliğini belirtebilirsiniz.
Deneyin
Uygulamayı tekrar çalıştırırsanız bu adıma ilişkin animasyonu görürsünüz.

Ay, Transition ayrıntısında belirtilen bir KeyPosition içinden geçtiği için bir yay izler.
<KeyPosition
motion:framePosition="50"
motion:motionTarget="@id/moon"
motion:keyPositionType="parentRelative"
motion:percentY="0.5"
/>
Bu KeyPosition öğesini şu şekilde okuyabilirsiniz: "framePosition 50 konumunda (animasyonun ortasında), parentRelative tarafından belirlenen koordinatlara göre (MotionLayout öğesinin tamamı) 50% Y kadar (ekranın ortasında) hareket ettirerek motionTarget @id/moon yolunu değiştirin."
Yani animasyonun yarısında, ayın ekranda% 50 aşağıda olan bir KeyPosition içinden geçmesi gerekiyor. Bu KeyPosition, X hareketini hiç değiştirmediği için ay, baştan sona yatay olarak hareket etmeye devam eder. MotionLayout, başlangıç ve bitiş arasında geçiş yaparken bu KeyPosition içinden geçen sorunsuz bir yol belirler.
Yakından bakarsanız jenerik metni ayın konumuyla sınırlanıyor. Neden dikey olarak da hareket etmiyor?

<Constraint
android:id="@id/credits"
...
motion:layout_constraintBottom_toBottomOf="@id/moon"
motion:layout_constraintTop_toTopOf="@id/moon"
/>
Görünüşe göre ayın izlediği yolu değiştirseniz bile ayın başlangıç ve bitiş noktaları 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ırlandırılır.
Kredilerin ay ile birlikte hareket etmesini isterseniz jeneriklere KeyPosition ekleyebilir veya @id/credits paketindeki başlangıç kısıtlamalarını değiştirebilirsiniz.
Sonraki bölümde, MotionLayout dilindeki farklı keyPositionType türlerini inceleyeceksiniz.
6. keyPositionType'ı anlama
Son adımda, yolu ekranın% 50'si oranında dengelemek için keyPosition parentRelative türünü kullandınız. keyPositionType özelliği, MotionLayout'un percentX veya percentY öğesine göre yolu nasıl değiştireceğini belirler.
<KeyFrameSet>
<KeyPosition
motion:framePosition="50"
motion:motionTarget="@id/moon"
motion:keyPositionType="parentRelative"
motion:percentY="0.5"
/>
</KeyFrameSet>
Olası üç 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, uzaydaki bir noktayı belirtmek için bir yöntem sağlar. Bunlar, ekrandaki bir konumu tanımlamak için de yararlıdır.
MotionLayout koordinat sistemleri bir alışveriş sepeti koordinat sistemidir. Bunun anlamı, bunların iki dik çizgiyle tanımlanan bir X ve Y ekseni vardır. Bunlar arasındaki temel fark, X ekseninin ekranda gittiği 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ındaki değerleri kullanır. Negatif değerlere ve 1.0 değerinden büyük değerlere izin verir. Örneğin, percentX değeri olan -2.0, X ekseninin ters yönüne iki kez gitmelidir.
Bunların hepsi Cebir dersine benziyorsa, aşağıdaki resimlere göz atın!
parentgöreli koordinatlar

parentRelative öğesinin keyPositionType özelliği, ekranla aynı koordinat sistemini kullanır. Tüm MotionLayout öğesinin sol üst tarafında (0, 0) ve sağ altta (1, 1) öğesini tanımlar.
Bu örnekteki ay yayını gibi, MotionLayout boyunca hareket eden bir animasyon oluşturmak istediğinizde parentRelative kullanabilirsiniz.
Bununla birlikte, bir yolu harekete göre değiştirmek, örneğin biraz eğmek istiyorsanız diğer iki koordinat sistemi daha iyi bir tercihtir.
deltagöreli koordinatlar

Delta, değişim için kullanılan bir matematik terimi olduğundan deltaRelative, "göreceli değişim" anlamına gelir. deltaRelativeKoordinatlarda(0,0) görünümün başlangıç konumu, (1,1) ise bitiş konumudur. X ve Y eksenleri ekranla hizalanır.
X ekseni ekranda her zaman yatay, Y ekseni ise ekranda her zaman dikeydir. parentRelative ile karşılaştırıldığında en önemli fark, koordinatların ekranda yalnızca görünümün hareket edeceği bölümünü tanımlamasıdır.
deltaRelative, yatay veya dikey hareketi ayrı olarak kontrol etmek için mükemmel bir koordinat sistemidir. Örneğin, sadece dikey (Y) hareketini %50'de tamamlayan ve yatay (X) animasyonuna devam eden bir animasyon oluşturabilirsiniz.
pathgöreli koordinatlar

MotionLayout bölgesindeki son koordinat sistemi pathRelative. X ekseni, hareket yolunu başından sonuna kadar izlediğinden diğer ikisinden oldukça farklıdır. Dolayısıyla (0,0) başlangıç konumu, (1,0) ise bitiş konumudur.
Bunu neden isteyesiniz? Özellikle de bu koordinat sistemi ekran koordinat sistemiyle aynı hizada olmadığından ilk bakışta oldukça şaşırtıcı.
pathRelative'ın birkaç konuda gerçekten kullanışlı olduğu anlaşılıyor.
- Animasyonun bir kısmı sırasında görünümün hızlandırılması, yavaşlatılması veya durdurulması. X boyutu her zaman görünümün izlediği yolla tam olarak eşleşeceğinden, söz konusu yoldaki belirli bir noktaya
framePositionulaşmak için birpathRelativeKeyPositionkullanabilirsiniz. Dolayısıyla,percentX="0.1"içerenframePosition="50"konumundaki birKeyPosition, animasyonun hareketin ilk% 10'luk kısmında seyahat etmek için gereken sürenin% 50'sini almasına neden olur. - Yola ince bir yay ekleme. Y boyutu harekete her zaman dik olduğundan, Y'nin değiştirilmesi eğrinin yolunu genel harekete göre değiştirir.
deltaRelativeçalışmadığında ikinci bir boyut eklemek.deltaRelative, tamamen yatay ve dikey hareketler için yalnızca tek bir yararlı boyut oluşturur. AncakpathRelativeher zaman kullanılabilir X ve Y koordinatları oluşturur.
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 bakıldığında yumuşak bir eğri oluşturulur ancak şekil daha çok "aya benzer" olabilir.
Birden çok KeyPosition öğesine sahip bir yolu değiştirme
MotionLayout, herhangi bir hareketi elde etmek için gereken sayıda KeyPosition tanımlayarak bir yolda daha fazla değişiklik yapabilir. Bu animasyon için bir yay oluşturacaksınız. Ancak dilerseniz ayı ekranın ortasında yukarı aşağı zıplatabilirsiniz.
xml/step4.xmladlı kişiyi aç. Bu segmentin aynı görünümlere ve son adımda eklediğinizKeyFramedeğerine sahip olduğunu görüyorsunuz.- Eğrinin üst kısmını yuvarlamak için
@id/moonyoluna ikiKeyPositionsdaha ekleyin. Bunlardan biri en üst noktaya ulaşmadan hemen önce, diğeri de arkadan 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'inde uygulanır ve @id/moon ürününün, ekranın üst kısmından% 60'lık bir yol boyunca hareket etmesine neden olur. %50'deki mevcut KeyPosition ile birleştirildiğinde bu, ayın takip edeceği yumuşak bir yay oluşturur.
MotionLayout içinde istediğiniz hareket yolunu elde etmek için ihtiyacınız kadar KeyPositions ekleyebilirsiniz. MotionLayout, her bir KeyPosition öğesini belirtilen framePosition saatinde uygulayacak ve KeyPositions cihazının tamamını kapsayan yumuşak bir hareketin nasıl oluşturulacağını çözecek.
Deneyin
- Uygulamayı tekrar çalıştırın. Animasyonun nasıl çalıştığını görmek için 4. Adım'a gidin. Ay'ı tıkladığınızda,
KeyFrameSet. maddede belirtilen her birKeyPositionboyunca ilerleyerek yolu başından sonuna kadar izler.
Kendi başınıza keşfedin
Diğer KeyFrame türlerine geçmeden önce, KeyPosition kullanarak ne tür efektler oluşturabileceğinizi görmek için KeyFrameSet öğesine biraz daha KeyPositions eklemeyi deneyin.
Animasyon sırasında ileri ve geri hareket eden karmaşık bir yolun nasıl oluşturulacağını gösteren bir örneği burada bulabilirsiniz.

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 bitirdiğinizde, bir 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 değerinin değiştirilmesi anlamına gelir. MotionLayout, KeyAttribute kullanılarak tüm görünümlerde birçok özelliğin animasyonunu destekler.
Bu adımda, Ay'ı ölçeklemek ve döndürmek için KeyAttribute aracını kullanacaksınız. Ay'ın yolculuğu neredeyse bitene kadar metnin görünümünü ertelemek için de bir KeyAttribute kullanacaksınız.
1. Adım: KeyAttribute ile yeniden boyutlandırın ve döndürün
- Son adımda oluşturduğunuz animasyonun aynısını içeren
xml/step5.xmldosyasını açın. Çeşitlilik sağlamak için bu ekranda arka plan olarak farklı bir alan resmi kullanılır. - Ayın boyut olarak genişlemesini ve dönmesini sağlamak için
keyFrame="50"vekeyFrame="100"içineKeyFrameSetiki taneKeyAttributeetiketi 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 ve% 100'ünde uygulanır. %50'lik ilk KeyAttribute, yayının en üstünde gerçekleşir ve görüntünün iki katına çıkarılmasına ve -360 derece (veya bir tam daire) döndürülmesine neden olur. İkinci KeyAttribute, ikinci dönüşü -720 dereceye (iki tam daire) bitirir ve scaleX ile scaleY değerleri varsayılan olarak 1,0 olduğundan boyutu tekrar normale çeker.
KeyPosition gibi, KeyAttribute da KeyFrame öğesinin ne zaman uygulanacağını ve hangi görünümün değiştirileceğini belirtmek için framePosition ve motionTarget öğelerini kullanır. MotionLayout, değişken animasyonlar oluşturmak için KeyPositions arasında arapolasyon yapar.
KeyAttributes, tüm görünümlere uygulanabilecek özellikleri destekler. Bunlar 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, boyutu scaleX ve scaleY ile ölçeklendirebilir veya görünümün konumunu X, Y veya Z biçiminde çevirebilirsiniz.
2. Adım: Kredilerin gösterilmesini geciktirin
Bu adımın hedeflerinden biri, animasyonu, animasyon neredeyse tamamlanana kadar jenerik metninin görünmeyecek şekilde güncellemektir.
- Kredilerin gösterilmesini ertelemek için
alphaöğesininkeyPosition="85"tarihine kadar 0 kalmasını sağlayan birKeyAttributedaha tanımlayın.MotionLayout, 0'dan 100 alfaya 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, @id/credits öğesinin alpha değerini animasyonun ilk% 85'i için 0,0'da tutar. Alfa 0'da başladığından, animasyonun ilk% 85'inde görünmez olur.
Bu KeyAttribute işleminin nihai etkisi, jeneriklerin animasyonun sonuna doğru görünmesidir. Bu şekilde, ekranın sağ köşesindeki ay ile koordineli çalışırlar.
Bir görünümdeki animasyonları geciktirirken diğer görünüm bu şekilde hareket eder. Böylece, kullanıcıya dinamik bir deneyim yaşatan etkileyici animasyonlar oluşturabilirsiniz.
Deneyin
- Uygulamayı tekrar çalıştırın ve animasyonun nasıl çalıştığını görmek için 5. Adım'a gidin. Ay'ı tıkladığınızda,
KeyFrameSetiçinde belirtilen her birKeyAttributeboyunca ilerleyerek yolu baştan sona izlersiniz.

Ay'ı iki tam daire şeklinde döndürdüğünüz için arkaya iki kez dönmeniz gerekir. Ayrıca jenerik, animasyon neredeyse bitene kadar görünmelerini geciktirir.
Kendi başınıza keşfetme
Son KeyFrame türüne geçmeden önce KeyAttributes içindeki diğer standart özellikleri değiştirmeyi deneyin. Örneğin, hangi animasyonu oluşturduğunu görmek için rotation öğesini rotationX olarak değiştirmeyi deneyin.
Deneyebileceğiniz standart özelliklerin listesi aşağıda verilmiştir:
android:visibilityandroid:alphaandroid:elevationandroid:rotationandroid:rotationXandroid:rotationYandroid:scaleXandroid:scaleYandroid:translationXandroid:translationYandroid:translationZ
9. Özel özellikleri değiştirme
Zengin animasyonlar, görünümün renginin veya diğer özelliklerinin değiştirilmesini içerir. MotionLayout, önceki görevde listelenen standart özelliklerden herhangi birini değiştirmek için KeyAttribute kullanabilir ancak diğer özellikleri belirtmek için CustomAttribute kullanırsınız.
CustomAttribute, belirleyici olan herhangi bir değeri ayarlamak için kullanılabilir. Örneğin, CustomAttribute kullanarak bir Görünümde backgroundColor'ı ayarlayabilirsiniz. MotionLayout, belirleyiciyi bulmak için yansıma özelliğini kullanır, ardından görünümü canlandırmak için tekrar tekrar çağırır.
Bu adımda, aşağıda gösterilen animasyonu oluşturmak amacıyla ayda colorFilter özelliğini ayarlamak için bir CustomAttribute kullanacaksınız.

Özel özellikleri tanımlama
- Başlamak için son adımda oluşturduğunuz animasyonun aynısını içeren
xml/step6.xmlöğesini açın. - Ayın rengini değiştirmek için
KeyFrameSetiçinkeyFrame="0",keyFrame="50"vekeyFrame="100".noktalarındakiCustomAttributeile ikiKeyAttributeekleyin.

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 bir CustomAttribute eklersiniz. CustomAttribute, KeyAttribute ile belirtilen framePosition oranında uygulanacak.
CustomAttribute içinde bir attributeName ve ayarlanacak bir değer belirtmelisiniz.
motion:attributeName, bu özel özellik tarafından çağrılacak belirleyicinin adıdır. Bu örnekte,DrawableüzerindekisetColorFilterçağrılır.motion:custom*Value, adda belirtilen türün özel değeridir. Bu örnekte, özel değer belirtilmiş bir renktir.
Özel değerler, aşağıdaki türlerden herhangi birine sahip olabilir:
- Renk
- Tamsayı
- Kayan
- Dize
- Boyut
- Boole
MotionLayout, bu API'yi kullanarak herhangi bir görünümde belirleyici sağlayan her şeyi canlandırabilir.
Deneyin
- Uygulamayı tekrar çalıştırın ve animasyonun nasıl çalıştığını görmek için 6. Adım'a gidin. Ay'ı tıkladığınızda,
KeyFrameSetiçinde belirtilen her birKeyAttributeboyunca ilerleyerek yolu baştan sona izlersiniz.

Daha fazla KeyFrames eklediğinizde MotionLayout, ayın yolunu düz bir çizgiden karmaşık bir eğriye dönüştürerek çift ters çevirme, yeniden boyutlandırma ve animasyonun ortasında bir renk değişikliği ekler.
Gerçek animasyonlarda, genellikle birkaç görünümü aynı anda farklı yollar ve hızlardaki hareketlerini kontrol ederek canlandırırsınız. Her görünüm için farklı bir KeyFrame belirtildiğinde, MotionLayout kullanarak birden çok görünümü canlandıran zengin animasyonların koreografisini oluşturmak mümkündür.
10. Etkinlikleri ve karmaşık yolları sürükleme
Bu adımda, karmaşık yollar ile OnSwipe kullanımını keşfedeceksiniz. Şimdiye kadar, ay animasyonu bir OnClick dinleyicisi tarafından tetiklenmiş ve belirli bir süre boyunca oynatılmıştır.
OnSwipe kullanarak karmaşık yolları olan animasyonları (ör. son birkaç adımda oluşturduğunuz ay animasyonu) kontrol etmek için OnSwipe işlevinin nasıl çalıştığını anlamanız gerekir.
1. Adım: On Kaydırma davranışını keşfedin
xml/step7.xmlsayfasını 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ıp 7. Adım'a gidin. Ayı yay çizgisi boyunca sürükleyerek akıcı bir animasyon elde edip edemeyeceğinize bakın.
Bu animasyonu çalıştırdığınızda pek iyi görünmez. Ay, yayın en üstüne ulaştığında zıplamaya başlar.

Hatayı anlamak için kullanıcı yayın ekranının hemen alt kısmına dokunduğunda ne olduğunu düşünün. OnSwipe etiketinde motion:touchAnchorSide="bottom" bulunduğundan 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 gitmediğinden önce yukarıya, sonra tekrar aşağıya iner. MotionLayout, kullanıcı yayının üst kısmını geçtiğinde ne yapacağını bilmez. Ay'ın altını izlediğiniz için kullanıcı buraya dokunduğunda bu görüntü neresine yerleştirilmelidir?

2. adım: Sağ tarafı kullanın
Bunun gibi hataları önlemek için her zaman 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 yönü tersine çevirir. OnSwipe onu takip etmeye çalıştığında yönü 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, yan kanalı normalden farklı bir yöne çekmek için dragDirection ile touchAnchorSide birleştirebilirsiniz. touchAnchorSide yalnızca tek bir yönde ilerlemeye devam eder ancak MotionLayout ürününe hangi yönün izleneceğini söyleyebilirsiniz. Örneğin, touchAnchorSide="bottom" değerini koruyup dragDirection="dragRight" ekleyebilirsiniz. Bu, MotionLayout ürününün görünümün alt konumunu izlemesine neden olur, ancak sağa doğru hareket ederken yalnızca konumunu dikkate alır (dikey hareketi göz ardı eder). Dolayısıyla, alt kısım yukarı ve aşağı inse bile OnSwipe ile doğru bir şekilde animasyon oluşturmaya devam eder.
- 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.
MotionLayout, karmaşık bir yay takip etse de kaydırma etkinliklerine tepki olarak animasyonu ilerletebilir.

11. Kodlu hareketli hareket
MotionLayout, CoordinatorLayout ile kullanıldığında zengin animasyonlar oluşturmak için kullanılabilir. Bu adımda, MotionLayout özelliğini 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.xmlürününde, çalışan birCoordinatorLayoutveAppBarLayoutyönteminin zaten oluşturulmuş olduğunu görüyorsunuz.
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 bir CoordinatorLayout kullanır. NestedScrollView yukarı kaydırıldığında AppBarLayout cihazına değişikliği bildirir. Android'de bu şekilde daraltılabilen bir araç çubuğu uygularsınız. Metnin kaydırılması "koordine edilir". başlığıyla daraltılabilir.
@id/motion_layout özelliğinin işaret ettiği hareket sahnesi, son adımdaki hareket sahnesine benziyor. Ancak OnSwipe beyanı, CoordinatorLayout ile çalışmasını sağlamak için kaldırılmıştır.
- Uygulamayı çalıştırın ve 8. Adım'a gidin. Metni kaydırdığınızda ayın hareket etmediğini görüyorsunuz.
2. Adım: MotionLayout'u kaydırın
MotionLayoutgörünümününNestedScrollViewkaydırılır kaydırmaz kaydırılmasını sağlamak içinmotion:minHeightvemotion:layout_scrollFlagsöğeleriniMotionLayoutöğesine ekleyin.
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ım'a gidin. Yukarı kaydırdıkça
MotionLayoutdaralır. Bununla birlikte, animasyon henüz kaydırma davranışına göre ilerlemez.
3. Adım: Hareketi kodla taşıyın
Step8Activity.ktuygulamasını açın . Kaydırma konumundaki değişiklikleriMotionLayoutadlı kullanıcıya 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ı mevcut kaydırma ofsetiyle her kaydırdığında çağrılacak bir OnOffsetChangedListener kaydeder.
MotionLayout, ilerleme durumunu ayarlayarak geçiş sürecini destekler. verticalOffset ile yüzdelik ilerleme durumu arasında dönüştürme 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.
MotionLayoutöğesinin, animasyonu kaydırma konumuna göre ilerleteceğini görürsünüz.

MotionLayout kullanarak özel dinamik daraltma araç çubuğu animasyonları oluşturabilirsiniz. Bir KeyFrames dizisi kullanarak çok çarpıcı efektler elde edebilirsiniz.
12. Tebrikler
Bu codelab'de MotionLayout ile ilgili temel API ele alınmıştır.
MotionLayout ile ilgili daha fazla örnek görmek için resmi örneği inceleyin. Belgeleri incelemeyi unutmayın.
Daha Fazla Bilgi
MotionLayout, bu codelab'de ele alınmayan başka özellikleri de destekler. Örneğin, tekrarlanan döngüleri olan yolları veya özellikleri kontrol etmenizi sağlayan KeyCycle, ve saat saatine göre animasyon yapmanıza olanak tanıyan KeyTimeCycle, gibi. Her biriyle ilgili örnekler için örneklere göz atın.
Bu kurstaki diğer codelab'lerin bağlantıları için Kotlin codelab'lerinde gelişmiş Android açılış sayfasına göz atın.