Mülk animasyon sistemi, neredeyse her şeyi canlandırmanıza olanak tanıyan sağlam bir çerçevedir. Ekrana çekilip çekilmemesinden bağımsız olarak, zaman içinde herhangi bir nesne özelliğini değiştirecek bir animasyon tanımlayabilirsiniz. Mülk animasyonu, bir özelliğin (nesnedeki alan) değerini belirli bir süre boyunca değiştirir. Bir şeyi canlandırmak için, canlandırmak istediğiniz nesne özelliğini (ör. bir nesnenin ekrandaki konumu, ne kadar süreyle canlandırmak istediğiniz ve arasında animasyon oluşturmak istediğiniz değerler) belirtirsiniz.
Mülk animasyonu sistemi, bir animasyonun aşağıdaki özelliklerini tanımlayabilmenizi sağlar:
- Süre: Animasyonun süresini belirtebilirsiniz. Varsayılan uzunluk 300 ms'dir.
- Zaman interpolasyonu: Özellik değerlerinin, animasyonun geçen süresinin bir fonksiyonu olarak nasıl hesaplanacağını belirtebilirsiniz.
- Tekrar sayısı ve davranışı: Bir animasyonun belirli bir sürenin sonuna geldiğinde tekrarlanıp tekrarlanmayacağını ve animasyonun kaç kez tekrarlanacağını belirtebilirsiniz. Animasyonun tersten oynatılmasını isteyip istemediğinizi de belirtebilirsiniz. Ters hıza ayarlanırsa, tekrar sayısına ulaşılana kadar animasyonu tekrar tekrar ileri, ardından geriye doğru oynatır.
- Animatör grupları: Animasyonları, birlikte, sırayla veya belirtilen gecikmelerden sonra oynatılan mantıksal kümeler halinde gruplandırabilirsiniz.
- Kare yenileme gecikmesi: Animasyonunuzun karelerinin ne sıklıkta yenileneceğini belirleyebilirsiniz. Varsayılan ayar her 10 ms'de bir yenilenecek şekilde ayarlanmıştır. Ancak uygulamanızın kareleri yenileme hızı, sistemin genel olarak ne kadar meşgul olduğuna ve sistemin temel zamanlayıcıyı ne kadar hızlı çalıştırabildiğine bağlıdır.
Tesis animasyonunun tam bir örneğini görmek için GitHub'daki CustomTransition örneğinde yer alan ChangeColor
sınıfına bakın.
Tesis animasyonu nasıl çalışır?
İlk olarak, bir animasyonun nasıl çalıştığını basit bir örnekle inceleyelim. Şekil 1'de, ekranda yatay konumunu temsil eden x
özelliğiyle canlandırılan varsayımsal bir nesne gösterilmektedir. Animasyonun süresi 40 ms'ye ve hareket mesafesi 40 piksele ayarlanmıştır. Varsayılan kare yenileme hızı olan 10 ms'de bir nesne yatay olarak 10 piksel hareket eder. 40 ms.nin sonunda, animasyon durur ve nesne 40 yatay konumda sona erer. Bu, nesnenin sabit bir hızda hareket ettiği anlamına gelen doğrusal interpolasyon içeren bir animasyon örneğidir.
Ayrıca, doğrusal olmayan bir interpolasyona sahip animasyonlar da belirtebilirsiniz. Şekil 2'de, animasyonun başında hızlanan ve animasyonun sonunda yavaşlayan varsayımsal bir nesne gösterilmektedir. Nesne, 40 ms'de doğrusal olmayan bir şekilde 40 piksel hareket etmeye devam eder. Bu animasyon başlangıçta yarı noktaya kadar hızlandırılır, ardından yarıdan sonuna kadar yavaşlar. Şekil 2'de gösterildiği gibi animasyonun başında ve sonunda kat edilen mesafe, ortasından daha azdır.
Mülk animasyon sisteminin önemli bileşenlerinin, yukarıda gösterilenlere benzer animasyonları nasıl hesapladığına ayrıntılı bir şekilde göz atalım. Şekil 3'te ana sınıfların birbirleriyle nasıl çalıştığı gösterilmiştir.
ValueAnimator
nesnesi, animasyonunuzun zamanlamasını (ör. animasyonun ne kadar süredir çalıştığı ve canlandırdığı özelliğin geçerli değeri) izler.
ValueAnimator
, animasyon interpolasyonunu tanımlayan bir TimeInterpolator
ve canlandırılan özelliğin değerlerinin nasıl hesaplanacağını tanımlayan bir TypeEvaluator
içerir. Örneğin, Şekil 2'de TimeInterpolator
değeri AccelerateDecelerateInterpolator
, TypeEvaluator
ise IntEvaluator
olur.
Bir animasyon başlatmak için ValueAnimator
oluşturun ve buna, canlandırmak istediğiniz özelliğin başlangıç ve bitiş değerleriyle birlikte animasyonun süresini verin. start()
yöntemini çağırdığınızda animasyon başlar. Animasyonun tamamı boyunca ValueAnimator
, animasyonun süresine ve geçen süreye göre 0 ile 1 arasında bir geçen kesir hesaplar. Geçen oran, animasyonun tamamlandığı sürenin yüzdesini temsil eder. 0 %0, 1 ise %100 anlamına gelir. Örneğin, Şekil 1'de toplam süre t = 40 ms olduğundan t = 10 ms'de geçen kesir 0, 25 olur.
ValueAnimator
, geçen kesiri hesaplamayı bitirdiğinde, interpolasyona tabi kesir hesaplamak için halihazırda ayarlı olan TimeInterpolator
değerini çağırır. İnterpolasyonlu kesir, geçen kesiri, ayarlanan zaman interpolasyonunu dikkate alan yeni bir kesirle eşler. Örneğin, Şekil 2'de animasyon yavaşça hızlandırıldığı için yaklaşık 0,15 interpole edilen kesir, geçen kesirden (t = 10 ms) göre daha azdır (t = 10 ms). Şekil 1'de interpolasyona tabi kesir her zaman geçen kesirle aynıdır.
İnterpole edilen kesir hesaplandığında ValueAnimator
; interpole edilen kesir, başlangıç değeri ve animasyonun bitiş değerine göre animasyon uyguladığınız özelliğin değerini hesaplamak için uygun TypeEvaluator
yöntemini çağırır. Örneğin, Şekil 2'de t = 10 ms'de interpolasyonlu kesir 0,15'tir. Dolayısıyla özelliğin o andaki değeri 0,15 × (40 - 0) veya 6 olur.
Mülk animasyonu ile görüntüleme animasyonu arasındaki farklar nelerdir?
Görüntüleme animasyonu sistemi, yalnızca View
nesneleri canlandırma olanağı sağlar. Bu nedenle, View
olmayan nesnelere animasyon eklemek isterseniz bunu yapmak için kendi kodunuzu uygulamanız gerekir. Görünüm animasyonu sistemi, animasyon uygulamak üzere bir View
nesnesinin yalnızca bazı özelliklerini (örneğin, bir Görünümün ölçeklenmesi ve döndürülmesi gibi) (arka plan rengi değil) göstermesi nedeniyle kısıtlanır.
Görüntüleme animasyonu sisteminin bir başka dezavantajı, Görünüm'ün kendisinin değil, yalnızca Görünümün çizildiği yerde değiştirilmesidir. Örneğin, ekranda hareket etmesi için bir düğmeyi canlandırdıysanız düğme doğru çiziliyor ancak düğmeyi tıklayabileceğiniz asıl konum değişmiyor. Bu işlemi gerçekleştirmek için kendi mantığınızı uygulamanız gerekir.
Mülk animasyonu sistemiyle bu kısıtlamalar tamamen kaldırılır ve herhangi bir nesnenin (Görünüm ve Görünüm olmayan öğeler) herhangi bir özelliğini canlandırabilirsiniz. Bu şekilde nesnenin kendisi değiştirilir. Tesis animasyon sistemi, animasyonu yürütme yönteminde de daha sağlamdır. En üst düzeyde, canlandırmak istediğiniz özelliklere (ör. renk, konum veya boyut) animasyonlar atar ve animasyonun interpolasyon ve birden fazla animatörün senkronizasyonu gibi özelliklerini tanımlayabilirsiniz.
Bununla birlikte, görüntüleme animasyonu sisteminin kurulumu daha az zaman alır ve yazmak için daha az kod gerektirir. Animasyon görüntüleme, yapmanız gereken her şeyi yapıyorsa veya mevcut kodunuz zaten istediğiniz şekilde çalışıyorsa özellik animasyon sistemini kullanmanıza gerek yoktur. Kullanım alanı ortaya çıkarsa farklı durumlarda her iki animasyon sistemini de kullanmak mantıklı olabilir.
API'ye genel bakış
Tesis animasyon sistemi API'lerinin çoğunu android.animation
içinde bulabilirsiniz. Görüntüleme animasyonu sistemi android.view.animation
bölgesinde zaten birçok interpolatör tanımladığından, bu interpolatörleri mülk animasyon sisteminde de kullanabilirsiniz. Aşağıdaki tablolarda, tesis animasyon sisteminin ana bileşenleri açıklanmaktadır.
Animator
sınıfı, animasyon oluşturmak için temel yapıyı sağlar. Bu sınıfı yalnızca animasyon değerlerini tam olarak destekleyecek şekilde genişletilmesi gereken minimum düzeyde işlev sunduğundan, normalde bu sınıfı doğrudan kullanmazsınız. Aşağıdaki alt sınıflar Animator
kapsamını genişletir:
Sınıf | Açıklama |
---|---|
ValueAnimator |
Animasyon uygulanacak özelliğin değerlerini de hesaplayan, mülk animasyonu için ana zamanlama motoru. Animasyon değerlerini hesaplayan tüm temel işlevlere sahiptir ve her animasyonun zamanlama ayrıntılarını, bir animasyonun tekrarlanıp tekrarlanmadığı hakkındaki bilgileri, güncelleme etkinliklerini alan işleyicileri ve değerlendirilecek özel türler ayarlama özelliğini içerir. Mülkleri canlandırmak için iki parça vardır: animasyonlu değerleri hesaplama ve bu değerleri canlandırılan nesnede ve mülkte ayarlama. ValueAnimator ikinci parçayı yürütmez. Bu nedenle, ValueAnimator tarafından hesaplanan değerlerde yapılan güncellemeleri dinlemeniz ve kendi mantığınızla canlandırmak istediğiniz nesneleri değiştirmeniz gerekir. Daha fazla bilgi için ValueAnimator ile Animasyon Oluşturma bölümüne bakın. |
ObjectAnimator |
Canlandırılacak bir hedef nesne ve nesne özelliği ayarlamanıza olanak tanıyan bir ValueAnimator alt sınıfı. Bu sınıf, animasyon için yeni bir değer hesaplarken özelliği buna uygun şekilde günceller. Hedef nesnelerde değerlere animasyon ekleme işlemini çok daha kolay hale getirdiği için çoğu zaman ObjectAnimator kullanmayı tercih edersiniz. Ancak ObjectAnimator hedef nesnede belirli erişimci yöntemlerinin bulunmasını zorunlu kılmak gibi birkaç kısıtlama daha olduğu için bazen ValueAnimator öğesini doğrudan kullanmak istersiniz. |
AnimatorSet |
Animasyonları gruplandırıp birbirleriyle ilişkili olarak çalışacak şekilde gruplandıran bir mekanizma sağlar. Animasyonları, sırayla veya belirtilen bir gecikmeden sonra oynatılacak şekilde ayarlayabilirsiniz. Daha fazla bilgi için Animasyon Gruplarıyla birden fazla animasyonun koreografisini oluşturma bölümüne bakın. |
Değerlendiriciler, özellik animasyon sistemine belirli bir özelliğin değerlerinin nasıl hesaplanacağını bildirir. Bu parametreler, bir Animator
sınıfı tarafından sağlanan zamanlama verilerini, animasyonun başlangıç ve bitiş değerlerini alıp bu verilere dayanarak özelliğin animasyonlu değerlerini hesaplar. Tesis animasyonu sistemi aşağıdaki değerlendiricileri sağlar:
Sınıf/Arayüz | Açıklama |
---|---|
IntEvaluator |
int mülklerinin değerlerini hesaplayan varsayılan değerlendirici. |
FloatEvaluator |
float mülklerinin değerlerini hesaplayan varsayılan değerlendirici. |
ArgbEvaluator |
Onaltılık değerler olarak temsil edilen renk özelliklerinin değerlerini hesaplayacak varsayılan değerlendirici. |
TypeEvaluator |
Kendi değerlendiricinizi oluşturmanıza olanak tanıyan bir arayüz. int , float veya renk olmayan bir nesne özelliğini canlandırıyorsanız nesne özelliğinin animasyonlu değerlerinin nasıl hesaplanacağını belirtmek için TypeEvaluator arayüzünü uygulamanız gerekir. Bu türleri varsayılan davranıştan farklı şekilde işlemek istiyorsanız int , float ve renk değerleri için de özel bir TypeEvaluator belirtebilirsiniz.
Özel değerlendirici yazma hakkında daha fazla bilgi için TypeEvaluator Kullanma bölümüne bakın. |
Zaman interpolatörü, bir animasyondaki belirli değerlerin zamanın bir fonksiyonu olarak nasıl hesaplandığını tanımlar. Örneğin, animasyonların tüm animasyon boyunca doğrusal olarak gerçekleşeceğini belirtebilirsiniz. Diğer bir deyişle, animasyon tüm zaman boyunca eşit şekilde hareket eder. Örneğin, animasyonların başında hızlanan ve sonunda yavaşlayan doğrusal olmayan bir zaman kullanacak şekilde de belirtebilirsiniz. Tablo 3'te, android.view.animation
içindeki interpolatörler açıklanmaktadır. Sağlanan interpolatörlerin hiçbiri ihtiyaçlarınıza uymuyorsa TimeInterpolator
arayüzünü uygulayın ve kendi arayüzünüzü oluşturun. Özel interpolatör yazma hakkında daha fazla bilgi için İnterpolatörleri kullanma bölümüne bakın.
Sınıf/Arayüz | Açıklama |
---|---|
AccelerateDecelerateInterpolator |
Değişim oranı yavaş başlayıp biten ancak ortalara doğru hızlanan bir interpolatör. |
AccelerateInterpolator |
Değişim oranı yavaş yavaş başlayıp daha sonra hızlanan bir interpolatördür. |
AnticipateInterpolator |
Değişikliği geriye doğru başlayıp ileri doğru kayan bir interpolatör. |
AnticipateOvershootInterpolator |
Değişikliği geriye doğru başlayıp ileri doğru hızla ilerleyip hedef değeri aşan ve son olarak son değere geri dönen bir interpolatör. |
BounceInterpolator |
Değişikliği en sonda geri dönen bir interpolatör. |
CycleInterpolator |
Animasyonu belirli sayıda döngü boyunca tekrarlanan bir interpolatör. |
DecelerateInterpolator |
Değişim oranı hızlı bir şekilde başlayıp yavaşlayan bir interpolatör. |
LinearInterpolator |
Değişim oranı sabit olan bir interpolatör. |
OvershootInterpolator |
Değişikliği ileri gidip son değeri aşan ve ardından geri gelen bir interpolatör. |
TimeInterpolator |
Kendi interpolatörünüzü uygulamanıza olanak tanıyan arayüz. |
ValueAnimator kullanarak animasyon uygulama
ValueAnimator
sınıfı, animasyon uygulamak için bir int
, float
veya renk değeri grubu belirterek animasyon süresi boyunca belirli bir türdeki değerleri canlandırmanıza olanak tanır. Fabrika yöntemlerinden birini çağırarak bir ValueAnimator
edinirsiniz: ofInt()
, ofFloat()
veya ofObject()
. Örnek:
Kotlin
ValueAnimator.ofFloat(0f, 100f).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f); animation.setDuration(1000); animation.start();
Bu kodda start()
yöntemi çalıştırıldığında ValueAnimator
, 1.000 ms'lik bir süre boyunca animasyonun 0 ile 100 arasındaki değerlerini hesaplamaya başlar.
Aşağıdakileri yaparak, animasyon oluşturulacak özel bir tür de belirtebilirsiniz:
Kotlin
ValueAnimator.ofObject(MyTypeEvaluator(), startPropertyValue, endPropertyValue).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue); animation.setDuration(1000); animation.start();
Bu kodda ValueAnimator
, start()
yöntemi çalışırken MyTypeEvaluator
tarafından sağlanan mantığı kullanarak 1.000 ms'lik bir süre boyunca startPropertyValue
ile endPropertyValue
arasındaki animasyonun değerlerini hesaplamaya başlar.
Animasyonun değerlerini, aşağıdaki kodda gösterildiği gibi ValueAnimator
nesnesine bir AnimatorUpdateListener
ekleyerek kullanabilirsiniz:
Kotlin
ValueAnimator.ofObject(...).apply { ... addUpdateListener { updatedAnimation -> // You can use the animated value in a property that uses the // same type as the animation. In this case, you can use the // float value in the translationX property. textView.translationX = updatedAnimation.animatedValue as Float } ... }
Java
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator updatedAnimation) { // You can use the animated value in a property that uses the // same type as the animation. In this case, you can use the // float value in the translationX property. float animatedValue = (float)updatedAnimation.getAnimatedValue(); textView.setTranslationX(animatedValue); } });
onAnimationUpdate()
yönteminde, güncellenen animasyon değerine erişebilir ve bunu görünümlerinizden birinin mülkünde kullanabilirsiniz. İşleyiciler hakkında daha fazla bilgi için Animasyon işleyicileri hakkındaki bölüme bakın.
ObjectAnimator kullanarak animasyon oluşturma
ObjectAnimator
, ValueAnimator
alt sınıfıdır (önceki bölümde açıklanmıştır) ve zamanlama motorunu ve ValueAnimator
değer hesaplamasını, hedef nesnenin adlandırılmış özelliğini canlandırma özelliğiyle birleştirir. Animasyonlu özellik otomatik olarak güncellendiğinden artık ValueAnimator.AnimatorUpdateListener
öğesini uygulamanız gerekmediğinden bu, herhangi bir nesnenin animasyonunu çok daha kolay hale getirir.
ObjectAnimator
örneği oluşturmak ValueAnimator
ile benzerdir ancak aynı zamanda nesneyi ve nesnenin özelliğinin adını da (Dize olarak) ve arasında animasyon oluşturulacak değerleri belirtirsiniz:
Kotlin
ObjectAnimator.ofFloat(textView, "translationX", 100f).apply { duration = 1000 start() }
Java
ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f); animation.setDuration(1000); animation.start();
ObjectAnimator
özelliklerinin doğru şekilde güncellenmesi için aşağıdakileri yapmanız gerekir:
- Canlandırmakta olduğunuz nesne özelliğinin
set<PropertyName>()
biçiminde bir belirleyici işlevi (deve durumunda) olmalıdır.ObjectAnimator
, animasyon sırasında özelliği otomatik olarak güncellediğinden, bu ayarlayıcı yöntemiyle mülke erişebilmesi gerekir. Örneğin, mülk adıfoo
isesetFoo()
yönteminizin olması gerekir. Bu setter yöntemi mevcut değilse üç seçeneğiniz vardır:- Gerekli haklara sahipseniz setter yöntemini sınıfa ekleyin.
- Değiştirme hakkına sahip olduğunuz bir sarmalayıcı sınıfı kullanın ve bu sarmalayıcının değeri geçerli bir setter yöntemiyle alıp orijinal nesneye yönlendirmesini sağlayın.
- Bunun yerine
ValueAnimator
politikasını kullanın.
ObjectAnimator
fabrika yöntemlerinden birindevalues...
parametresi için yalnızca bir değer belirtirseniz bunun animasyonun bitiş değeri olduğu varsayılır. Dolayısıyla, animasyon uyguladığınız nesne özelliğinin, animasyonun başlangıç değerini elde etmek için kullanılan bir getter işlevine sahip olması gerekir. Getter işleviget<PropertyName>()
biçiminde olmalıdır. Örneğin, mülk adıfoo
isegetFoo()
yönteminizin olması gerekir.- Canlandırdığınız mülkün "alıcı (gerekirse)" ve ayarlayıcı yöntemleri,
ObjectAnimator
için belirlediğiniz başlangıç ve bitiş değerleriyle aynı türde çalışmalıdır. Örneğin, aşağıdakiObjectAnimator
öğesini oluşturursanıztargetObject.setPropName(float)
vetargetObject.getPropName()
öğelerine sahip olmanız gerekir:ObjectAnimator.ofFloat(targetObject, "propName", 1f)
- Canlandırdığınız özellik veya nesneye bağlı olarak, ekranı güncellenen animasyonlu değerlerle yeniden çizmeye zorlamak için bir Görünümde
invalidate()
yöntemini çağırmanız gerekebilir. Bu işlemionAnimationUpdate()
geri çağırmasında yaparsınız. Örneğin, bir Çekilebilir nesnenin renk özelliğine animasyon eklemek, yalnızca nesne kendini yeniden çizdiğinde ekranda güncelleme yapılmasına neden olur. View'dakisetAlpha()
vesetTranslationX()
gibi özellik belirleyicilerin tümü, Görünümü düzgün bir şekilde geçersiz kılar. Bu nedenle, bu yöntemleri yeni değerlerle çağırırken Görünümü geçersiz kılmanız gerekmez. İşleyiciler hakkında daha fazla bilgi için Animasyon işleyicileri hakkındaki bölüme bakın.
AnimatorSet kullanarak birden fazla animasyonun koreografisini oluşturma
Çoğu durumda, başka bir animasyonun ne zaman başladığına veya bittiğine bağlı olan bir animasyonu oynatmak istersiniz. Android sistemi, animasyonları bir AnimatorSet
içinde gruplandırmanıza olanak tanır. Böylece animasyonların eş zamanlı olarak mı, sıralı olarak mı yoksa belirli bir gecikmeden sonra mı başlatılacağını belirleyebilirsiniz. Ayrıca AnimatorSet
nesneleri birbirinin içine yerleştirebilirsiniz.
Aşağıdaki kod snippet'i, aşağıdaki Animator
nesnelerini aşağıdaki şekilde oynatır:
bounceAnim
oynatır.squashAnim1
,squashAnim2
,stretchAnim1
vestretchAnim2
aynı anda çalar.bounceBackAnim
oynatır.fadeAnim
oynatır.
Kotlin
val bouncer = AnimatorSet().apply { play(bounceAnim).before(squashAnim1) play(squashAnim1).with(squashAnim2) play(squashAnim1).with(stretchAnim1) play(squashAnim1).with(stretchAnim2) play(bounceBackAnim).after(stretchAnim2) } val fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply { duration = 250 } AnimatorSet().apply { play(bouncer).before(fadeAnim) start() }
Java
AnimatorSet bouncer = new AnimatorSet(); bouncer.play(bounceAnim).before(squashAnim1); bouncer.play(squashAnim1).with(squashAnim2); bouncer.play(squashAnim1).with(stretchAnim1); bouncer.play(squashAnim1).with(stretchAnim2); bouncer.play(bounceBackAnim).after(stretchAnim2); ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(bouncer).before(fadeAnim); animatorSet.start();
Animasyon dinleyicileri
Aşağıda açıklanan işleyicilerle bir animasyon süresince önemli etkinlikleri dinleyebilirsiniz.
Animator.AnimatorListener
onAnimationStart()
- Animasyon başladığında çağrılır.onAnimationEnd()
- Animasyon sona erdiğinde çağrılır.onAnimationRepeat()
: Animasyon kendini tekrar ettiğinde çağrılır.onAnimationCancel()
: Animasyon iptal edildiğinde çağrılır. İptal edilen bir animasyon, nasıl sona erdirildiklerine bakılmaksızınonAnimationEnd()
işlevini de çağırır.
ValueAnimator.AnimatorUpdateListener
-
onAnimationUpdate()
: Animasyonun her karesinde çağrılır. Bir animasyon sırasındaValueAnimator
tarafından oluşturulan hesaplanmış değerleri kullanmak için bu etkinliği dinleyin. Değeri kullanmak için etkinliğe geçirilenValueAnimator
nesnesini sorgulayarakgetAnimatedValue()
yöntemiyle mevcut animasyonlu değeri alın.ValueAnimator
kullanıyorsanız bu işleyicinin uygulanması gerekir.Canlandırdığınız özellik veya nesneye bağlı olarak, ekranın söz konusu alanını yeni animasyonlu değerlerle yeniden çizmeye zorlamak için bir Görünümde
invalidate()
çağırmanız gerekebilir. Örneğin, bir Çekilebilir nesnenin renk özelliğine animasyon eklemek, yalnızca nesne kendini yeniden çizdiğinde ekranda güncelleme yapılmasına neden olur. View'dakisetAlpha()
vesetTranslationX()
gibi özellik belirleyicilerin tümü Görünümü düzgün bir şekilde geçersiz kılar. Bu nedenle, bu yöntemleri yeni değerlerle çağırırken Görünümü geçersiz kılmanız gerekmez.
-
Animator.AnimatorListener
arayüzünün tüm yöntemlerini uygulamak istemiyorsanız Animator.AnimatorListener
arayüzünü uygulamak yerine AnimatorListenerAdapter
sınıfını genişletebilirsiniz. AnimatorListenerAdapter
sınıfı, geçersiz kılmayı seçebileceğiniz yöntemlerin boş uygulamalarını sağlar.
Örneğin, aşağıdaki kod snippet'i yalnızca onAnimationEnd()
geri çağırması için bir AnimatorListenerAdapter
oluşturur:
Kotlin
ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply { duration = 250 addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { balls.remove((animation as ObjectAnimator).target) } }) }
Java
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); fadeAnim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { balls.remove(((ObjectAnimator)animation).getTarget()); }
ViewGroup nesnelerinde düzen değişikliklerini canlandırma
Tesis animasyonu sistemi, ViewGroup nesnelerinde yapılan değişiklikleri canlandırma yeteneğinin yanı sıra View nesnelerinin kendilerini canlandırmak için kolay bir yol da sunar.
LayoutTransition
sınıfıyla bir ViewGroup içindeki düzen değişikliklerini canlandırabilirsiniz. Bir ViewGroup içindeki görünümler, bir ViewGroup'a eklediğinizde veya kaldırıldığında ya da VISIBLE
, INVISIBLE
veya GONE
ile bir View'un setVisibility()
yöntemini çağırdığınızda görünen ve kaybolan bir animasyondan geçebilir. Görünümleri eklediğinizde veya kaldırdığınızda, ViewGroup'taki geri kalan Görünümler,
yeni konumlarında hareket edebilir. setAnimator()
yöntemini çağırıp bir Animator
nesnesini aşağıdaki LayoutTransition
sabit değerlerinden biriyle ileterek bir LayoutTransition
nesnesinde şu animasyonları tanımlayabilirsiniz:
APPEARING
: Kapsayıcıda görünen öğelerde çalıştırılan animasyonu belirten bir işaret.CHANGE_APPEARING
: Kapsayıcıda yeni bir öğenin görünmesi nedeniyle değişen öğelerde çalıştırılan animasyonu belirten işaret.DISAPPEARING
: Kapsayıcıdan kaybolan öğelerde çalıştırılan animasyonu belirten bir işaret.CHANGE_DISAPPEARING
: Bir öğenin kapsayıcıdan kaldırılması nedeniyle değişen öğelerde çalıştırılan animasyonu belirten işaret.
Düzen geçişlerinizin görünümünü özelleştirmek için bu dört etkinlik türü için kendi özel animasyonlarınızı tanımlayabilir veya animasyon sistemine varsayılan animasyonları kullanmasını söyleyebilirsiniz.
ViewGroup için android:animateLayoutchanges
özelliğini true
olarak ayarlamak için aşağıdakileri yapın:
<LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/verticalContainer" android:animateLayoutChanges="true" />
Bu özelliğin doğru değerine ayarlanması, ViewGroup'a eklenen veya kaldırılan Görünümlerin yanı sıra ViewGroup'taki geri kalan Görünümler için de otomatik olarak animasyon uygular.
StateListAnimator'ı kullanarak görünüm durumu değişikliklerini canlandırma
StateListAnimator
sınıfı, bir görünümün durumu değiştiğinde çalışan animatörler tanımlamanızı sağlar. Bu nesne, bir Animator
nesnesi için sarmalayıcı görevi görür ve belirtilen görünüm durumu ("basıldı" veya "odaklanmış" gibi) her değiştiğinde bu animasyonu çağırır.
StateListAnimator
, her biri StateListAnimator
sınıfı tarafından tanımlanan farklı bir görünüm durumu belirten kök <selector>
öğesi ve alt <item>
öğelerine sahip XML kaynağında tanımlanabilir. Her <item>
, bir özellik animasyonu grubunun tanımını içerir.
Örneğin, aşağıdaki dosya basıldığında görünümün x ve y ölçeğini değiştiren bir durum listesi animatörü oluşturur:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- the pressed state; increase x and y size to 150% --> <item android:state_pressed="true"> <set> <objectAnimator android:propertyName="scaleX" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1.5" android:valueType="floatType"/> <objectAnimator android:propertyName="scaleY" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1.5" android:valueType="floatType"/> </set> </item> <!-- the default, non-pressed state; set x and y size to 100% --> <item android:state_pressed="false"> <set> <objectAnimator android:propertyName="scaleX" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1" android:valueType="floatType"/> <objectAnimator android:propertyName="scaleY" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1" android:valueType="floatType"/> </set> </item> </selector>
Durum listesi animatörünü bir görünüme eklemek için
android:stateListAnimator
özelliğini aşağıdaki gibi ekleyin:
<Button android:stateListAnimator="@xml/animate_scale" ... />
Artık bu düğmenin durumu değiştiğinde animate_scale.xml
içinde tanımlanan animasyonlar kullanılmaktadır.
Alternatif olarak, kodunuzdaki bir görünüme durum listesi animatörü atamak için AnimatorInflater.loadStateListAnimator()
yöntemini kullanabilir ve View.setStateListAnimator()
yöntemiyle görünümünüze animatör atayabilirsiniz.
Görünümün özelliklerine animasyon eklemek yerine, AnimatedStateListDrawable
işlevini kullanarak durum değişiklikleri arasında çekilebilir bir animasyon oynatabilirsiniz.
Android 5.0'daki sistem widget'larından bazıları varsayılan olarak bu animasyonları kullanır. Aşağıdaki örnekte, AnimatedStateListDrawable
kaynağının XML kaynağı olarak nasıl tanımlanacağı gösterilmektedir:
<!-- res/drawable/myanimstatedrawable.xml --> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- provide a different drawable for each state--> <item android:id="@+id/pressed" android:drawable="@drawable/drawableP" android:state_pressed="true"/> <item android:id="@+id/focused" android:drawable="@drawable/drawableF" android:state_focused="true"/> <item android:id="@id/default" android:drawable="@drawable/drawableD"/> <!-- specify a transition --> <transition android:fromId="@+id/default" android:toId="@+id/pressed"> <animation-list> <item android:duration="15" android:drawable="@drawable/dt1"/> <item android:duration="15" android:drawable="@drawable/dt2"/> ... </animation-list> </transition> ... </animated-selector>
TypeEvaluator kullanma
Android sistemi tarafından bilinmeyen bir türe animasyon eklemek isterseniz TypeEvaluator
arayüzünü uygulayarak kendi değerlendiricinizi oluşturabilirsiniz. Android sistemi tarafından bilinen türler, IntEvaluator
, FloatEvaluator
ve ArgbEvaluator
türü değerlendiricileri tarafından desteklenen int
, float
veya renktir.
TypeEvaluator
arayüzünde yalnızca bir yöntem kullanılabilir: evaluate()
yöntemi. Bu, kullanmakta olduğunuz animatörün, animasyonun geçerli noktasında animasyonlu mülkünüz için uygun bir değer döndürmesini sağlar. FloatEvaluator
sınıfı bunun nasıl yapılacağını gösterir:
Kotlin
private class FloatEvaluator : TypeEvaluator<Any> { override fun evaluate(fraction: Float, startValue: Any, endValue: Any): Any { return (startValue as Number).toFloat().let { startFloat -> startFloat + fraction * ((endValue as Number).toFloat() - startFloat) } } }
Java
public class FloatEvaluator implements TypeEvaluator { public Object evaluate(float fraction, Object startValue, Object endValue) { float startFloat = ((Number) startValue).floatValue(); return startFloat + fraction * (((Number) endValue).floatValue() - startFloat); } }
Not: ValueAnimator
(veya ObjectAnimator
) çalıştırıldığında, animasyonun geçerli geçen bölümünü (0 ile 1 arasında bir değer) hesaplar ve ardından, hangi interpolatörü kullandığınıza bağlı olarak bunun interpolasyona tabi bir sürümünü hesaplar. İnterpole edilen kesir, TypeEvaluator
öğenizin fraction
parametresi aracılığıyla aldığı orandır. Bu nedenle, animasyonlu değerleri hesaplarken interpolatörü dikkate almanız gerekmez.
İnterpolatör kullanın
İnterpolatör, bir animasyondaki belirli değerlerin zaman fonksiyonu olarak nasıl hesaplandığını tanımlar. Örneğin, animasyonların tüm animasyon boyunca doğrusal olarak gerçekleşeceğini belirtebilirsiniz. Diğer bir deyişle, animasyon tüm zaman boyunca eşit şekilde hareket eder. Örneğin, animasyonların başında veya sonunda hızlanma veya yavaşlama kullanarak doğrusal olmayan bir zaman kullanacak şekilde animasyonlar belirtebilirsiniz.
Animasyon sistemindeki interpolatörler, animasyonda geçen süreyi temsil eden Animatörlerden bir kesir alır. İnterpolatörler, bu oranı, sağlamayı amaçladıkları animasyon türüyle uyumlu olacak şekilde değiştirir. Android sistemi, android.view.animation package
bölgesinde bir dizi yaygın interpolatör sağlar. Bunların hiçbiri ihtiyaçlarınıza uymuyorsa TimeInterpolator
arayüzünü uygulayıp kendi arayüzünüzü oluşturabilirsiniz.
Örnek olarak, varsayılan interpolatör AccelerateDecelerateInterpolator
ve LinearInterpolator
tarafından interpolasyon uygulanan kesirlerin nasıl hesaplandığı aşağıda gösterilmiştir.
LinearInterpolator
, geçen oran üzerinde herhangi bir etkisi yoktur. AccelerateDecelerateInterpolator
, animasyona doğru hızlanarak yavaşlar. Aşağıdaki yöntemler bu interpolatörlerin mantığını tanımlar:
AccelerateDecelerateInterpolator
Kotlin
override fun getInterpolation(input: Float): Float = (Math.cos((input + 1) * Math.PI) / 2.0f).toFloat() + 0.5f
Java
@Override public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; }
Lineer İnterpolatör
Kotlin
override fun getInterpolation(input: Float): Float = input
Java
@Override public float getInterpolation(float input) { return input; }
Aşağıdaki tabloda, 1.000 ms süren bir animasyon için bu interpolatörler tarafından hesaplanan yaklaşık değerler gösterilmektedir:
geçen ms | Geçen kesir/İnterpole edilmiş oran (Doğrusal) | İnterpole edilmiş kesir (Hızlandır/yavaşla) |
---|---|---|
0 | 0 | 0 |
200 | 0,2 | 0,1 |
400 | 0,4 | 0,345 |
600 | 0,6 | 0,8 |
800 | 0,8 | 0,9 |
1.000 | 1 | 1 |
Tabloda gösterildiği gibi LinearInterpolator
, değerleri aynı hızda değiştirir (geçen her 200 ms için 0,2). AccelerateDecelerateInterpolator
, değerleri LinearInterpolator
ile karşılaştırıldığında 200 ms ile 600 ms arasında, daha yavaş ve 600 ms ile 1.000 ms arasında değiştirir.
Animasyon karelerini belirtme
Keyframe
nesnesi, bir animasyonun belirli bir zamanındaki belirli bir durumu tanımlamanızı sağlayan bir zaman/değer çiftinden oluşur. Her animasyon karesinin, önceki animasyon karesinin zamanı ile bu animasyon karesinin zamanı arasındaki zaman aralığındaki davranışını kontrol etmek için kendi interpolatörü de olabilir.
Bir Keyframe
nesnesini somutlaştırmak için uygun Keyframe
türünü elde etmek üzere fabrika yöntemlerinden birini (ofInt()
, ofFloat()
veya ofObject()
) kullanmanız gerekir. Daha sonra, bir PropertyValuesHolder
nesnesi almak için ofKeyframe()
fabrika yöntemini çağırırsınız. Nesneyi aldığınızda, PropertyValuesHolder
nesnesini ve canlandırılacak nesneyi geçirerek bir animatör elde edebilirsiniz. Aşağıdaki kod snippet'inde bunun nasıl yapılacağı gösterilmektedir:
Kotlin
val kf0 = Keyframe.ofFloat(0f, 0f) val kf1 = Keyframe.ofFloat(.5f, 360f) val kf2 = Keyframe.ofFloat(1f, 0f) val pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2) ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation).apply { duration = 5000 }
Java
Keyframe kf0 = Keyframe.ofFloat(0f, 0f); Keyframe kf1 = Keyframe.ofFloat(.5f, 360f); Keyframe kf2 = Keyframe.ofFloat(1f, 0f); PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2); ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation); rotationAnim.setDuration(5000);
Görüntülemeleri canlandır
Mülk animasyon sistemi, View nesnelerinin basitleştirilmiş animasyonuna olanak tanır ve görünüm animasyon sistemine göre birkaç avantaj sunar. Görüntüleme animasyonu sistemi, çizilme şeklini değiştirerek View nesnelerini dönüştürdü. Görünümün değiştirilebilecek herhangi bir özelliği olmadığı için bu işlem her Görünümün kapsayıcısında gerçekleştirildi. Bu durum, Görünüme animasyon uygulanmasına neden oldu ancak Görünüm nesnesinin kendisinde herhangi bir değişikliğe neden olmadı. Bu durum, bir nesnenin ekranda farklı bir konumda çizilmiş olsa bile hâlâ orijinal konumunda mevcut olması gibi bir davranışa yol açıyordu. Android 3.0'da bu dezavantajı ortadan kaldırmak için yeni özelliklerin yanı sıra karşılık gelen "alıcı ve setter" yöntemleri eklenmiştir.
Mülk animasyon sistemi, Görünüm nesnelerindeki gerçek özellikleri değiştirerek ekrandaki Görünümler'i canlandırabilir. Buna ek olarak, Görünümler, özellikleri her değiştirildiğinde ekranı yenilemek için invalidate()
yöntemini de otomatik olarak çağırır. View
sınıfında, özellik animasyonlarını kolaylaştıran yeni özellikler şunlardır:
translationX
vetranslationY
: Bu özellikler, Görünüm'ün düzen kapsayıcısı tarafından ayarlanan sol ve üst koordinatlarına göre nerede bir delta olarak konumlandırılacağını kontrol eder.rotation
,rotationX
verotationY
: Bu özellikler, pivot noktası etrafında döndürmeyi 2D (rotation
özelliği) ve 3D olarak kontrol eder.scaleX
vescaleY
: Bu özellikler, bir Görünümün pivot noktası çevresinde 2D ölçeklemesini kontrol eder.pivotX
vepivotY
: Bu özellikler, etrafında döndürme ve ölçeklendirme dönüşümlerinin gerçekleştiği pivot noktanın konumunu kontrol eder. Pivot noktası, varsayılan olarak nesnenin merkezinde bulunur.x
vey
: Bunlar, Görünümün kapsayıcısındaki son konumunu, sol ve üst değerler ile çeviriX ve çeviriY değerlerinin toplamı olarak açıklayan basit yardımcı program özellikleridir.alpha
: Görünümde alfa şeffaflığını gösterir. Bu değer varsayılan olarak 1'dir (opak). 0 değeri tam şeffaflığı temsil eder (görünmez).
View nesnesinin rengi veya döndürme değeri gibi bir özelliğini canlandırmak için tek yapmanız gereken bir özellik animatörü oluşturmak ve canlandırmak istediğiniz View özelliğini belirtmektir. Örnek:
Kotlin
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f)
Java
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
Animatör oluşturma hakkında daha fazla bilgi için ValueAnimator ve ObjectAnimator ile animasyon oluşturma bölümlerine bakın.
ViewPropertyAnimator kullanarak animasyon uygulama
ViewPropertyAnimator
, tek bir temel Animator
nesnesi kullanarak View
öğesinin çeşitli özelliklerini paralel olarak canlandırmak için basit bir yol sağlar. Görünüm özelliklerinin gerçek değerlerini değiştirdiği ancak aynı anda birçok özelliği canlandırdığında daha verimli olduğu için ObjectAnimator
işlevine çok benzer davranır. Ayrıca, ViewPropertyAnimator
kodu çok daha kısa ve öz
ve okuması daha kolay. Aşağıdaki kod snippet'leri, bir görünümün x
ve y
özelliğini eş zamanlı olarak canlandırırken birden çok ObjectAnimator
nesnesi, tek bir ObjectAnimator
ve ViewPropertyAnimator
öğesinin kullanılması arasındaki farkları göstermektedir.
Birden çok ObjectAnimator nesnesi
Kotlin
val animX = ObjectAnimator.ofFloat(myView, "x", 50f) val animY = ObjectAnimator.ofFloat(myView, "y", 100f) AnimatorSet().apply { playTogether(animX, animY) start() }
Java
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f); ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f); AnimatorSet animSetXY = new AnimatorSet(); animSetXY.playTogether(animX, animY); animSetXY.start();
Bir Nesne Animatörü
Kotlin
val pvhX = PropertyValuesHolder.ofFloat("x", 50f) val pvhY = PropertyValuesHolder.ofFloat("y", 100f) ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start()
Java
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f); ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start();
ViewPropertyAnimator
Kotlin
myView.animate().x(50f).y(100f)
Java
myView.animate().x(50f).y(100f);
ViewPropertyAnimator
hakkında daha ayrıntılı bilgi edinmek için ilgili Android Developers blog yayınına bakın.
Animasyonları XML olarak bildirme
Özellik animasyonu sistemi, özellik animasyonlarını programatik olarak yapmak yerine XML ile bildirmenizi sağlar. Animasyonlarınızı XML'de tanımlayarak, animasyonlarınızı birden fazla etkinlikte kolayca yeniden kullanabilir ve animasyon sırasını daha kolay bir şekilde düzenleyebilirsiniz.
Android 3.1'den itibaren, yeni mülk animasyon API'lerini kullanan animasyon dosyalarını eski animasyon görüntüleme çerçevesini kullananlardan ayırt etmek için mülk animasyonlarına ait XML dosyalarını res/animator/
dizinine kaydetmeniz gerekir.
Aşağıdaki tesis animasyonu sınıflarında, aşağıdaki XML etiketleriyle XML bildirimi desteği bulunur:
ValueAnimator
-<animator>
ObjectAnimator
-<objectAnimator>
AnimatorSet
-<set>
XML bildiriminizde kullanabileceğiniz özellikleri bulmak için Animasyon kaynakları bölümüne bakın. Aşağıdaki örnekte iki nesne animasyonu grubu sırayla oynatılır ve iç içe yerleştirilmiş ilk grup iki nesne animasyonunu birlikte oynatır:
<set android:ordering="sequentially"> <set> <objectAnimator android:propertyName="x" android:duration="500" android:valueTo="400" android:valueType="intType"/> <objectAnimator android:propertyName="y" android:duration="500" android:valueTo="300" android:valueType="intType"/> </set> <objectAnimator android:propertyName="alpha" android:duration="500" android:valueTo="1f"/> </set>
Bu animasyonu çalıştırmak için kodunuzdaki XML kaynaklarını bir AnimatorSet
nesnesine dönüştürmeniz ve daha sonra animasyon grubunu başlatmadan önce tüm animasyonlar için hedef nesneleri ayarlamanız gerekir. setTarget()
çağrısı, kolaylık sağlamak amacıyla AnimatorSet
öğesinin tüm alt öğeleri için tek bir hedef nesne ayarlar. Aşağıdaki kod bunun nasıl yapılacağını gösterir:
Kotlin
(AnimatorInflater.loadAnimator(myContext, R.animator.property_animator) as AnimatorSet).apply { setTarget(myObject) start() }
Java
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.animator.property_animator); set.setTarget(myObject); set.start();
Aşağıdaki örnekte gösterildiği gibi XML'de bir ValueAnimator
belirtmeniz de mümkündür:
<animator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:valueType="floatType" android:valueFrom="0f" android:valueTo="-100f" />
Kodunuzda önceki ValueAnimator
öğesini kullanmak için nesneyi şişirmeniz, bir AnimatorUpdateListener
eklemeniz, güncellenmiş animasyon değerini almanız ve bunu aşağıdaki kodda gösterildiği gibi görünümlerinizden birinin özelliğinde kullanmanız gerekir:
Kotlin
(AnimatorInflater.loadAnimator(this, R.animator.animator) as ValueAnimator).apply { addUpdateListener { updatedAnimation -> textView.translationX = updatedAnimation.animatedValue as Float } start() }
Java
ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator); xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator updatedAnimation) { float animatedValue = (float)updatedAnimation.getAnimatedValue(); textView.setTranslationX(animatedValue); } }); xmlAnimator.start();
Özellik animasyonlarını tanımlamaya yönelik XML söz dizimi hakkında bilgi için Animasyon kaynakları bölümüne bakın.
Kullanıcı arayüzü performansı üzerindeki olası etkiler
Kullanıcı arayüzünü güncelleyen animatörler, animasyonun çalıştırıldığı her kare için ekstra oluşturma çalışmasına neden olur. Bu nedenle, kaynakları yoğun olarak kullanan animasyonlar kullanmak uygulamanızın performansını olumsuz yönde etkileyebilir.
Kullanıcı arayüzünüzü canlandırmak için gereken çalışmalar, oluşturma ardışık düzeninin animasyon aşamasına eklenir. Profil GPU Oluşturma'yı etkinleştirip animasyon sahnesini izleyerek animasyonlarınızın uygulamanızın performansını etkileyip etkilemediğini öğrenebilirsiniz. Daha fazla bilgi için Profil GPU oluşturma adım adım açıklamalı kılavuzu bölümüne bakın.