Yay fiziğini kullanarak hareketi canlandırma

Compose yöntemini deneyin
Jetpack Compose, Android için önerilen kullanıcı arayüzü araç setidir. Compose'da animasyonları nasıl kullanacağınızı öğrenin.

Fiziğe dayalı hareket, kuvvetle yönlendirilir. Yay kuvveti, etkileşimi ve hareketi yönlendiren kuvvetlerden biridir. Yay kuvveti aşağıdaki özelliklere sahiptir: sönümleme ve sertlik. Yay tabanlı animasyonlarda değer ve hız, her kareye uygulanan yay kuvvetine göre hesaplanır.

Uygulamanızdaki animasyonların yalnızca tek bir yönde yavaşlamasını istiyorsanız bunun yerine sürtünmeye dayalı bir hızla kaydırma animasyonu kullanmayı düşünebilirsiniz.

Yay animasyonunun yaşam döngüsü

Yaya tabanlı animasyonlarda SpringForce sınıfı, yayın sertliğini, sönümleme oranını ve son konumunu özelleştirmenize olanak tanır. Animasyon başlar başlamaz yay kuvveti, her karede animasyon değerini ve hızı günceller. Animasyon, yay kuvveti dengeye ulaşana kadar devam eder.

Örneğin, bir uygulama simgesini ekranın etrafında sürükleyip daha sonra parmağınızı simgeden kaldırarak bıraktığınızda simge, görünmez ancak tanıdık bir güç tarafından orijinal yerine geri çekilir.

Şekil 1'de benzer bir yay efekti gösterilmektedir. Dairenin ortasındaki artı işareti (+), dokunma hareketiyle uygulanan kuvveti gösterir.

İlkbahar sürümü
Şekil 1. İlkbahar temalı efekt

Yay animasyonu oluşturma

Uygulamanız için yay animasyonu oluşturmayla ilgili genel adımlar şunlardır:

Aşağıdaki bölümlerde, yay animasyonu oluşturmayla ilgili genel adımlar ayrıntılı olarak ele alınmaktadır.

Destek kitaplığını ekleme

Fizik tabanlı destek kitaplığını kullanmak için destek kitaplığını projenize aşağıdaki şekilde eklemeniz gerekir:

  1. Uygulama modülünüzün build.gradle dosyasını açın.
  2. Destek kitaplığını dependencies bölümüne ekleyin.

    Modern

            dependencies {
                def dynamicanimation_version = '1.0.0'
                implementation "androidx.dynamicanimation:dynamicanimation:$dynamicanimation_version"
            }
            

    Kotlin

            dependencies {
                val dynamicanimation_version = "1.0.0"
                implementation("androidx.dynamicanimation:dynamicanimation:$dynamicanimation_version")
            }
            

    Bu kitaplığın mevcut sürümlerini görüntülemek için sürümler sayfasındaki Dynamicanimation ile ilgili bilgilere bakın.

Yay animasyonu oluşturma

SpringAnimation sınıfı, bir nesne için yay animasyonu oluşturmanıza olanak tanır. Yay animasyonu oluşturmak için SpringAnimation sınıfının bir örneğini oluşturmanız, bir nesne, animasyon eklemek istediğiniz nesnenin bir özelliği ve animasyonun durmasını istediğiniz isteğe bağlı bir son yay konumu sağlamanız gerekir.

Not: Yay animasyonu oluşturulurken yayın son konumu isteğe bağlıdır. Ancak animasyon başlatılmadan önce tanımlanması gerekir.

Kotlin

val springAnim = findViewById<View>(R.id.imageView).let { img ->
    // Setting up a spring animation to animate the view’s translationY property with the final
    // spring position at 0.
    SpringAnimation(img, DynamicAnimation.TRANSLATION_Y, 0f)
}

Java

final View img = findViewById(R.id.imageView);
// Setting up a spring animation to animate the view’s translationY property with the final
// spring position at 0.
final SpringAnimation springAnim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y, 0);

Yaya dayalı animasyon, görünüm nesnelerindeki gerçek özellikleri değiştirerek ekrandaki görünümleri canlandırabilir. Sistemde aşağıdaki görünümler kullanılabilir:

  • ALPHA: Görünümdeki alfa şeffaflığını gösterir. Değer varsayılan olarak 1'dir (opak). 0 değeri ise tam şeffaflığı (görünür değil) ifade eder.
  • TRANSLATION_X, TRANSLATION_Y ve TRANSLATION_Z: Bu özellikler, görünümün düzen kapsayıcısı tarafından ayarlanan sol koordinat, üst koordinat ve yükseklik değerinden fark olarak nerede bulunduğunu kontrol eder.
  • ROTATION, ROTATION_X ve ROTATION_Y: Bu özellikler, 2D'de (rotation özelliği) ve pivot noktası etrafında 3D'de döndürmeyi kontrol eder.
  • SCROLL_X ve SCROLL_Y: Bu özellikler, kaynağın sol ve üst kenarının kaydırma ofsetini piksel cinsinden belirtir. Ayrıca sayfanın ne kadar kaydırıldığına dair konumu da gösterir.
  • SCALE_X ve SCALE_Y: Bu özellikler, bir görünümün pivot noktası etrafındaki 2D ölçeklendirmesini kontrol eder.
  • X, Y ve Z: Bunlar, görünümün kapsayıcısındaki son konumunu açıklayan temel yardımcı özelliklerdir.

İşleyicileri kaydetme

DynamicAnimation sınıfı iki dinleyici sağlar: OnAnimationUpdateListener ve OnAnimationEndListener. Bu dinleyiciler, animasyon değerinde değişiklik olduğunda ve animasyon sona erdiğinde olduğu gibi animasyondaki güncellemeleri dinler.

OnAnimationUpdateListener

Zincirleme animasyon oluşturmak için birden fazla görünümü canlandırmak istediğinizde, mevcut görünümün özelliğinde her değişiklik olduğunda geri çağırma almak üzere OnAnimationUpdateListener ayarlayabilirsiniz. Geri çağırma, diğer görünümü, mevcut görünümün özelliğinde meydana gelen değişikliğe göre yay konumunu güncellemesi için bilgilendirir. Dinleyiciyi kaydetmek için aşağıdaki adımları uygulayın:

  1. addUpdateListener() yöntemini çağırın ve işleyiciyi animasyona ekleyin.

    Not: Güncelleme dinleyicisini animasyon başlamadan önce kaydetmeniz gerekir. Ancak güncelleme dinleyicisi, animasyon değeri değişikliklerinde kare başına güncellemeye ihtiyacınız varsa kaydedilmelidir. Güncelleme dinleyicisi, animasyonun ayrı bir iş parçacığında çalışmasını engeller.

  2. Arayanı geçerli nesnedeki değişiklik hakkında bilgilendirmek için onAnimationUpdate() yöntemini geçersiz kılın. Aşağıdaki örnek kod, OnAnimationUpdateListener genel kullanımını gösterir.

Kotlin

// Setting up a spring animation to animate the view1 and view2 translationX and translationY properties
val (anim1X, anim1Y) = findViewById<View>(R.id.view1).let { view1 ->
    SpringAnimation(view1, DynamicAnimation.TRANSLATION_X) to
            SpringAnimation(view1, DynamicAnimation.TRANSLATION_Y)
}
val (anim2X, anim2Y) = findViewById<View>(R.id.view2).let { view2 ->
    SpringAnimation(view2, DynamicAnimation.TRANSLATION_X) to
            SpringAnimation(view2, DynamicAnimation.TRANSLATION_Y)
}

// Registering the update listener
anim1X.addUpdateListener { _, value, _ ->
    // Overriding the method to notify view2 about the change in the view1’s property.
    anim2X.animateToFinalPosition(value)
}

anim1Y.addUpdateListener { _, value, _ -> anim2Y.animateToFinalPosition(value) }

Java

// Creating two views to demonstrate the registration of the update listener.
final View view1 = findViewById(R.id.view1);
final View view2 = findViewById(R.id.view2);

// Setting up a spring animation to animate the view1 and view2 translationX and translationY properties
final SpringAnimation anim1X = new SpringAnimation(view1,
        DynamicAnimation.TRANSLATION_X);
final SpringAnimation anim1Y = new SpringAnimation(view1,
    DynamicAnimation.TRANSLATION_Y);
final SpringAnimation anim2X = new SpringAnimation(view2,
        DynamicAnimation.TRANSLATION_X);
final SpringAnimation anim2Y = new SpringAnimation(view2,
        DynamicAnimation.TRANSLATION_Y);

// Registering the update listener
anim1X.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() {

// Overriding the method to notify view2 about the change in the view1’s property.
    @Override
    public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float value,
                                  float velocity) {
        anim2X.animateToFinalPosition(value);
    }
});

anim1Y.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() {

  @Override
    public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float value,
                                  float velocity) {
        anim2Y.animateToFinalPosition(value);
    }
});

OnAnimationEndListener

OnAnimationEndListener bir animasyonun sonunu bildirir. Dinleyiciyi, animasyon dengeye ulaştığında veya iptal edildiğinde geri çağırma alacak şekilde ayarlayabilirsiniz. Dinleyiciyi kaydetmek için aşağıdaki adımları uygulayın:

  1. addEndListener() yöntemini çağırın ve işleyiciyi animasyona ekleyin.
  2. Bir animasyon dengeye ulaştığında veya iptal edildiğinde bildirim almak için onAnimationEnd() yöntemini geçersiz kılın.

Dinleyicileri kaldırma

Animasyon güncelleme geri aramalarını ve animasyon sonu geri aramalarını almayı durdurmak için sırasıyla removeUpdateListener() ve removeEndListener() yöntemlerini çağırın.

Animasyon başlangıç değerini ayarlama

Animasyonun başlangıç değerini ayarlamak için setStartValue() yöntemini çağırın ve animasyonun başlangıç değerini iletin. Başlangıç değerini ayarlamazsanız animasyon, başlangıç değeri olarak nesnenin özelliğinin geçerli değerini kullanır.

Animasyon değeri aralığını ayarlama

Özellik değerini belirli bir aralıkla sınırlamak istediğinizde minimum ve maksimum animasyon değerlerini ayarlayabilirsiniz. Ayrıca, alfa (0-1 arası) gibi doğal aralığı olan özellikleri canlandırmanız durumunda aralığı kontrol etmenize de yardımcı olur.

  • Minimum değeri ayarlamak için setMinValue() yöntemini çağırın ve özelliğin minimum değerini iletin.
  • Maksimum değeri ayarlamak için setMaxValue() yöntemini çağırın ve özelliğin maksimum değerini iletin.

Her iki yöntem de değerin ayarlandığı animasyonu döndürür.

Not: Başlangıç değerini ayarladıysanız ve bir animasyon değeri aralığı tanımladıysanız başlangıç değerinin minimum ve maksimum değer aralığında olduğundan emin olun.

Başlangıç hızını ayarlama

Başlangıç hızı, animasyon özelliğinin animasyonun başlangıcındaki değişim hızını tanımlar. Varsayılan başlangıç hızı saniyede sıfır piksel olarak ayarlanır. Hızı, dokunma hareketlerinin hızıyla veya başlangıç hızı olarak sabit bir değer kullanarak ayarlayabilirsiniz. Sabit bir değer sağlamayı seçerseniz değeri saniyede dp cinsinden tanımlamanızı ve ardından saniyede piksel cinsine dönüştürmenizi öneririz. Değeri saniyede dp cinsinden tanımlamak, hızın yoğunluktan ve form faktörlerinden bağımsız olmasını sağlar. Değeri saniyede piksele dönüştürme hakkında daha fazla bilgi için Saniyede dp'yi saniyede piksele dönüştürme bölümüne bakın.

Hızı ayarlamak için setStartVelocity() yöntemini çağırın ve hızı saniyede piksel cinsinden iletin. Bu yöntem, hızın ayarlandığı yay kuvveti nesnesini döndürür.

Not: Dokunma hareketlerinin hızını almak ve hesaplamak için GestureDetector.OnGestureListener veya VelocityTracker sınıf yöntemlerini kullanın.

Kotlin

findViewById<View>(R.id.imageView).also { img ->
    SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply {
        
        // Compute velocity in the unit pixel/second
        vt.computeCurrentVelocity(1000)
        val velocity = vt.yVelocity
        setStartVelocity(velocity)
    }
}

Java

final View img = findViewById(R.id.imageView);
final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y);

// Compute velocity in the unit pixel/second
vt.computeCurrentVelocity(1000);
float velocity = vt.getYVelocity();
anim.setStartVelocity(velocity);

Saniyedeki dp'yi saniyedeki piksele dönüştürme

Bir yayın hızı, saniyede piksel cinsinden olmalıdır. Hızın başlangıcı olarak sabit bir değer sağlamayı seçerseniz değeri saniyede dp cinsinden sağlayın ve ardından saniyede piksel cinsine dönüştürün. Dönüşüm için applyDimension() TypedValue sınıfındaki yöntemi kullanın. Aşağıdaki örnek koda bakın:

Kotlin

val pixelPerSecond: Float =
    TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpPerSecond, resources.displayMetrics)

Java

float pixelPerSecond = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpPerSecond, getResources().getDisplayMetrics());

Yay özelliklerini ayarlama

SpringForce sınıfı, sönümleme oranı ve sertlik gibi her bir yay özelliğinin alıcı ve ayarlayıcı yöntemlerini tanımlar. Yay özelliklerini ayarlamak için yay kuvveti nesnesini almanız veya özellikleri ayarlayabileceğiniz özel bir yay kuvveti oluşturmanız önemlidir. Özel yay kuvveti oluşturma hakkında daha fazla bilgi için Özel yay kuvveti oluşturma bölümüne bakın.

İpucu: Setter yöntemlerini kullanırken tüm setter yöntemleri spring force nesnesini döndürdüğünden yöntem zinciri oluşturabilirsiniz.

Sönümleme oranı

Sönümleme oranı, yay salınımındaki kademeli azalmayı ifade eder. Sönümleme oranını kullanarak, titreşimlerin bir sıçramadan diğerine ne kadar hızlı şekilde azalacağını tanımlayabilirsiniz. Yayı sönümlemenin dört farklı yolu vardır:

  • Aşırı sönümleme, sönümleme oranı birden büyük olduğunda meydana gelir. Bu, nesnenin dinlenme konumuna yavaşça dönmesini sağlar.
  • Kritik sönümleme, sönümleme oranı bire eşit olduğunda gerçekleşir. Bu sayede nesne, en kısa sürede dinlenme konumuna döner.
  • Damping oranı birden az olduğunda yetersiz sönümleme meydana gelir. Bu, nesnenin dinlenme konumunu geçerek birden çok kez aşmasına ve ardından yavaş yavaş dinlenme konumuna ulaşmasına olanak tanır.
  • Sönümsüzlük, sönümleme oranı sıfıra eşit olduğunda meydana gelir. Nesnenin sonsuza kadar salınmasına olanak tanır.

Sönümleme oranını yaya eklemek için aşağıdaki adımları uygulayın:

  1. Sönümleme oranını eklemek için yayı almak üzere getSpring() yöntemini çağırın.
  2. setDampingRatio() yöntemini çağırın ve yaya eklemek istediğiniz sönümleme oranını iletin. Yöntemi, sönümleme oranının ayarlandığı yay kuvveti nesnesini döndürür.

    Not: Sönüm oranı negatif olmayan bir sayı olmalıdır. Sönümleme oranını sıfır olarak ayarlarsanız yay asla dinlenme konumuna ulaşmaz. Başka bir deyişle, sonsuza kadar salınır.

Sistemde aşağıdaki sönüm oranı sabitleri kullanılabilir:

Şekil 2: Yüksek hemen çıkma oranı

Şekil 3: Orta sıçrama

Şekil 4: Düşük hemen çıkma

Şekil 5: Geri sekme yok

Varsayılan sönümleme oranı DAMPING_RATIO_MEDIUM_BOUNCY olarak ayarlanmıştır.

Kotlin

findViewById<View>(R.id.imageView).also { img ->
    SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply {
        
        // Setting the damping ratio to create a low bouncing effect.
        spring.dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY
        
    }
}

Java

final View img = findViewById(R.id.imageView);
final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y);

// Setting the damping ratio to create a low bouncing effect.
anim.getSpring().setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY);

Sertlik

Sertlik, yayın gücünü ölçen yay sabitini tanımlar. Sert bir yay, dinlenme konumunda olmadığında bağlı olduğu nesneye daha fazla kuvvet uygular. Yaya sertlik eklemek için aşağıdaki adımları uygulayın:

  1. Sertlik eklemek için yayı almak üzere getSpring() yöntemini çağırın.
  2. setStiffness() yöntemini çağırın ve yaya eklemek istediğiniz sertlik değerini iletin. Yöntemi, sertliğin ayarlandığı yay kuvveti nesnesini döndürür.

    Not: Sertlik pozitif bir sayı olmalıdır.

Sistemde aşağıdaki sertlik sabitleri kullanılabilir:

Şekil 6: Yüksek sertlik

Şekil 7: Orta sertlik

Şekil 8: Düşük sertlik

Şekil 9: Çok düşük sertlik

Varsayılan sertlik STIFFNESS_MEDIUM olarak ayarlanmıştır.

Kotlin

findViewById<View>(R.id.imageView).also { img ->
    SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply {
        
        // Setting the spring with a low stiffness.
        spring.stiffness = SpringForce.STIFFNESS_LOW
        
    }
}

Java

final View img = findViewById(R.id.imageView);
final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y);

// Setting the spring with a low stiffness.
anim.getSpring().setStiffness(SpringForce.STIFFNESS_LOW);

Özel yay kuvveti oluşturma

Varsayılan yay kuvvetini kullanmak yerine özel bir yay kuvveti oluşturabilirsiniz. Özel yay kuvveti, aynı yay kuvveti örneğini birden fazla yay animasyonunda paylaşmanıza olanak tanır. Yay kuvvetini oluşturduktan sonra sönümleme oranı ve sertlik gibi özellikleri ayarlayabilirsiniz.

  1. SpringForce nesnesi oluşturun.

    SpringForce force = new SpringForce();

  2. İlgili yöntemleri çağırarak özellikleri atayın. Ayrıca bir yöntem zinciri de oluşturabilirsiniz.

    force.setDampingRatio(DAMPING_RATIO_LOW_BOUNCY).setStiffness(STIFFNESS_LOW);

  3. Yayı animasyona ayarlamak için setSpring() yöntemini çağırın.

    setSpring(force);

Animasyonu başlat

Yay animasyonunu iki şekilde başlatabilirsiniz: start() veya animateToFinalPosition() yöntemini çağırarak. Her iki yöntem de ana iş parçacığında çağrılmalıdır.

animateToFinalPosition() yöntemi iki görev gerçekleştirir:

  • Yayın son konumunu ayarlar.
  • Başlamadıysa animasyonu başlatır.

Bu yöntem, yayın son konumunu güncelleyip gerekirse animasyonu başlattığından, animasyonun akışını değiştirmek için bu yöntemi istediğiniz zaman çağırabilirsiniz. Örneğin, zincirleme yay animasyonunda bir görünümün animasyonu başka bir görünüme bağlıdır. Bu tür bir animasyon için animateToFinalPosition() yöntemini kullanmak daha uygundur. Bu yöntemi zincirleme yay animasyonunda kullandığınızda, bir sonraki güncellemek istediğiniz animasyonun şu anda çalışıp çalışmadığı konusunda endişelenmenize gerek kalmaz.

Şekil 10'da, bir görünümün animasyonunun başka bir görünüme bağlı olduğu zincirleme yay animasyonu gösterilmektedir.

Zincirli yay demosu
Şekil 10. Chained spring demosu

animateToFinalPosition() yöntemini kullanmak için animateToFinalPosition() yöntemini çağırın ve yayın dinlenme konumunu iletin. Yayın dinlenme konumunu setFinalPosition() yöntemini çağırarak da ayarlayabilirsiniz.

start() yöntemi, özellik değerini başlangıç değerine hemen ayarlamaz. Özellik değeri, çizim geçişinden önce gerçekleşen her animasyon darbesinde değişir. Bu nedenle, değerler hemen ayarlanmış gibi değişiklikler bir sonraki kareye yansıtılır.

Kotlin

findViewById<View>(R.id.imageView).also { img ->
    SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply {
        
        // Starting the animation
        start()
        
    }
}

Java

final View img = findViewById(R.id.imageView);
final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y);

// Starting the animation
anim.start();

Animasyonu iptal etme

Animasyonu iptal edebilir veya sonuna atlayabilirsiniz. Animasyonu iptal etmeniz veya animasyonun sonuna atlamanız gereken ideal durum, kullanıcı etkileşiminin animasyonun hemen sonlandırılmasını gerektirdiği zamandır. Bu durum genellikle kullanıcı bir uygulamadan aniden çıktığında veya görünüm görünmez hale geldiğinde ortaya çıkar.

Animasyonu sonlandırmak için kullanabileceğiniz iki yöntem vardır. cancel() yöntemi, animasyonu bulunduğu değerde sonlandırır. skipToEnd() yöntemi ise animasyonu son değere atlayıp sonlandırır.

Animasyonu sonlandırmadan önce yayın durumunu kontrol etmeniz önemlidir. Durum sönümlenmemişse animasyon asla dinlenme konumuna ulaşamaz. Yayın durumunu kontrol etmek için canSkipToEnd() yöntemini çağırın. Yay sönümlenmişse yöntem true, aksi takdirde false değerini döndürür.

Yayın durumunu öğrendikten sonra, skipToEnd() yöntemini veya cancel() yöntemini kullanarak animasyonu sonlandırabilirsiniz. cancel() yöntemi yalnızca ana ileti dizisinde çağrılmalıdır.

Not: Genel olarak, skipToEnd() yöntemi görsel atlamaya neden olur.