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.
ConstraintLayout
hakkında bilgi edinin.ConstraintLayout
hakkında daha fazla bilgi edinmek için Kısıtlama Düzeni codelab'ini okuyun.
Yapacaklarınız
ConstraintSets
veMotionLayout
ile animasyon tanımlayın- Sürükleme etkinliklerine göre animasyon uygulama
- Animasyonu
KeyPosition
ile değiştirin - Özellikleri
KeyAttribute
ile değiştirin - Animasyonları kodla çalıştırma
- Daraltılabilir başlıkları
MotionLayout
ile canlandırın
Gerekenler
- Android Studio 4.0 (
MotionLayout
dü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:
ConstraintLayout
alt sınıfı olan birMotionLayout,
. Animasyonlu olacak tüm görünümleriMotionLayout
etiketinin 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/layout
içindeactivity_step1.xml.
uygulamasını açın. Burada, içinde tek birImageView
yıldız bulunan ve içinde ton uygulanmış birConstraintLayout
var.
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
start
ConstraintSet
seçilmiştir. Ayrıca, aralarındaki oku tıklayarakstart
ileend
arası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,
start
ConstraintSet
bilgileri 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,
start
ConstraintSet
ö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
start
ConstraintSet'i seçin
- Seçim panelinde
red_star
simgesini seçin. Şu andalayout
Kaynağı gösteriliyor. Bu, değerin buConstraintSet
içinde kısıtlanmadığı anlamına gelir. Kısıtlama Oluşturma için sağ üstteki kalem simgesini kullanın.
- Genel bakış panelinde
start
ConstraintSet
seçildiğinde,red_star
öğesininstart
Kaynağını gösterdiğini onaylayın. - Özellikler panelinde,
start
ConstraintSet
içindered_star
seç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.xml
dosyası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
end
ConstraintSet'i seçin.
end
ConstraintSet
içindered_star
içinConstraint
eklemek ü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
bottom
veend
iç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.xml
uygulaması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
constraintSetStart
uygulanı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
start
ileend
arası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_star
olarak 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
toggle
için birclickAction
özelliği ekleyin.
- Hareket Düzenleyici'nin oluşturduğu kodu görmek için
activity_step1_scene.xml
uygulaması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
öğesininclickAction
kadarı, tıklandığında başlangıç ve bitiş durumu arasında geçiş yapacak.clickAction
ile 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.xml
dü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.xml
hareket sahnesini açın. start
baş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.0
olanalpha
değ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/credits
altı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ınalpha
bitiş değeri1.0
olarak 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.
OnSwipe
etiketini<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.xml
vexml/step3.xml
öğelerini açın.ImageView
veTextView
simgelerinde ay ve jenerik metni yer alıyor. - Hareket sahnesi dosyasını (
xml/step3.xml
) açın.@id/start
ile@id/end
arasında birTransition
değ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 veMotionLayout
etiketinemotion: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
KeyPosition
temsil 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 sahneyeKeyPosition
ekleyin.KeyPosition
etiketi,Transition
etiketinin 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
, yolukeyPositionType
olarak değiştirir.parentRelative
,pathRelative
veyadeltaRelative
olabilir (sonraki adımda açıklandığı gibi). percentX | percentY
,framePosition
iç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. deltaRelative
Koordinatlarda(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
framePosition
ulaşmak için birpathRelative
KeyPosition
kullanabilirsiniz. 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. AncakpathRelative
her 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.xml
adlı kişiyi aç. Bu segmentin aynı görünümlere ve son adımda eklediğinizKeyFrame
değerine sahip olduğunu görüyorsunuz.- Eğrinin üst kısmını yuvarlamak için
@id/moon
yoluna ikiKeyPositions
daha 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 birKeyPosition
boyunca 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.xml
dosyası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çineKeyFrameSet
iki taneKeyAttribute
etiketi 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 birKeyAttribute
daha 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,
KeyFrameSet
içinde belirtilen her birKeyAttribute
boyunca 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:visibility
android:alpha
android:elevation
android:rotation
android:rotationX
android:rotationY
android:scaleX
android:scaleY
android:translationX
android:translationY
android: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
KeyFrameSet
içinkeyFrame="0"
,keyFrame="50"
vekeyFrame="100".
noktalarındakiCustomAttribute
ile ikiKeyAttribute
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 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,
KeyFrameSet
içinde belirtilen her birKeyAttribute
boyunca 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.xml
sayfasını açın ve mevcutOnSwipe
beyanı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
touchAnchorSide
değeriniright
olarak 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
OnSwipe
uygulaması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.xml
uygulamasını açın. layout/activity_step8.xml
ürününde, çalışan birCoordinatorLayout
veAppBarLayout
yö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
MotionLayout
görünümününNestedScrollView
kaydırılır kaydırmaz kaydırılmasını sağlamak içinmotion:minHeight
vemotion: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
MotionLayout
daralır. Bununla birlikte, animasyon henüz kaydırma davranışına göre ilerlemez.
3. Adım: Hareketi kodla taşıyın
Step8Activity.kt
uygulamasını açın . Kaydırma konumundaki değişiklikleriMotionLayout
adlı 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.