Yay fiziğini kullanarak hareketi canlandırma

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

Fizik temelli hareket kuvvetle desteklenir. Etkileşime ve harekete yön veren kuvvetlerden biri yay kuvvetidir. Yay kuvveti şu özelliklere sahiptir: sönümleme ve sertlik. Yay tabanlı bir animasyonda, değer ve hız, her kareye uygulanan yay kuvvetine göre hesaplanır.

Uygulamanızın animasyonlarının yalnızca bir yönde yavaşlamasını istiyorsanız bunun yerine sürtünmeye dayalı bir fırlatma animasyonu kullanmayı düşünün.

Bir bahar animasyonunun yaşam döngüsü

Yay tabanlı bir animasyonda 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 animasyon değerini ve her bir karedeki hızı günceller. Animasyon, yay kuvveti dengeye ulaşana kadar devam eder.

Örneğin, bir uygulama simgesini ekranda sürükler ve daha sonra parmağınızı simgeden kaldırarak serbest bırakırsanız, simge görünmez ama tanıdık bir güç tarafından orijinal yerine geri çekilir.

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

İlkbahar sürümü
Şekil 1. İlkbahar sürümü etkisi

İlkbahar animasyonu oluşturma

Uygulamanız için bir bahar animasyonu oluşturmaya yönelik genel adımlar şöyledir:

Aşağıdaki bölümlerde bir ilkbahar animasyonu oluşturmanın genel adımları ayrıntılı olarak ele alınmaktadır.

Destek kitaplığını ekleme

Fiziğe dayalı 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 geçerli sürümlerini görüntülemek için sürümler sayfasındaki Dinamik Animasyon bilgilerine bakın.

İlkbahar animasyonu oluşturma

SpringAnimation sınıfı, bir nesne için yay animasyonu oluşturmanıza olanak tanır. Bir yay animasyonu oluşturmak için SpringAnimation sınıfının bir örneğini oluşturmanız ve bir nesne, canlandırmak istediğiniz bir nesnenin özelliğini ve animasyonun kalmasını istediğiniz isteğe bağlı bir nihai yay konumunu sağlamanız gerekir.

Not: Yay animasyonu oluşturulurken yayının son konumu isteğe bağlıdır. Yine de, animasyona başlamadan önce bunun 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);

İlkbahara 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ı temsil eder. Değer varsayılan olarak 1'dir (opak). 0 değeri tam şeffaflığı temsil eder (görünmez).
  • 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 bakımından delta olarak nerede bulunduğunu kontrol eder.
  • ROTATION, ROTATION_X ve ROTATION_Y: Bu özellikler, pivot noktası etrafında döndürmeyi 2D (rotation özelliği) ve 3D olarak kontrol eder.
  • SCROLL_X ve SCROLL_Y: Bu özellikler, sol kaynağın ve üst kenarın kaydırma ofsetini piksel cinsinden belirtir. Konum, sayfanın ne kadar kaydırıldığını da belirtir.
  • SCALE_X ve SCALE_Y: Bu özellikler, bir görünümün pivot noktası çevresinde 2D ölçeklendirmesini kontrol eder.
  • X, Y ve Z: Bunlar, görünümün kendi kapsayıcısındaki son konumunu açıklayan temel yardımcı program özellikleridir.

İşleyicileri kaydedin

DynamicAnimation sınıfı iki işleyici sağlar: OnAnimationUpdateListener ve OnAnimationEndListener. Bu işleyiciler, animasyon değerinde bir değişiklik olması ve animasyonun sona ermesi gibi animasyon güncellemelerini izler.

OnAnimationUpdateListener

Zincirli animasyon oluşturmak için birden fazla görünümü canlandırmak istediğinizde, geçerli görünümün özelliğinde her değişiklik olduğunda geri çağırma almak için OnAnimationUpdateListener parametresini ayarlayabilirsiniz. Geri çağırma, geçerli görünümün mülkünde gerçekleşen değişikliğe göre ilkbahar konumunu güncellemesini için diğer görünüme bildirir. Dinleyiciyi kaydetmek için aşağıdaki adımları uygulayın:

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

    Not: Animasyon başlamadan önce güncelleme işleyiciyi kaydetmeniz gerekir. Bununla birlikte, güncelleme işleyici yalnızca animasyon değeri değişikliklerinde kare başına güncellemeye ihtiyacınız olduğunda kaydedilmelidir. Güncelleme işleyici, animasyonun ayrı bir iş parçacığında çalışmasını engeller.

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

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. İşleyiciyi, animasyon dengeye ulaştığında veya iptal edildiğinde geri çağırması 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.

İşleyicileri kaldır

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

Animasyon başlangıç değerini ayarla

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ğer aralığını ayarla

Özellik değerini belirli bir aralıkla sınırlamak istediğinizde minimum ve maksimum animasyon değerlerini ayarlayabilirsiniz. Alfa gibi (0-1) içsel bir aralığa sahip özellikleri canlandırıyorsanız aralığın kontrol edilmesine 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ı ayarla

Başlangıç hızı, animasyonun başında animasyon özelliğinin değişme hızını tanımlar. Varsayılan başlangıç hızı, saniyede sıfır piksel olarak ayarlanmıştır. Hızı, dokunma hareketleriyle 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 daha sonra bu değeri saniyedeki piksele dönüştürmenizi öneririz. Değerin saniyede dp/dp cinsinden tanımlanması, hızın yoğunluk ve form faktörlerinden bağımsız olmasını sağlar. Değeri saniyedeki piksele dönüştürme hakkında daha fazla bilgi için Saniyedeki dp'yi piksel/saniyeye dönüştürme bölümüne bakın.

Hızı ayarlamak için setStartVelocity() yöntemini çağırın ve hızı piksel/saniye cinsinden iletin. 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 piksel/saniyeye dönüştürme

Bir yayın hızı, saniye başına piksel cinsinden olmalıdır. Hızın başlangıcı olarak sabit bir değer sağlamayı seçerseniz değeri saniye başına dp cinsinden sağlayın ve daha sonra, saniyedeki piksel sayısına dönüştürün. Dönüştürme için TypedValue sınıfındaki applyDimension() yöntemini kullanın. Aşağıdaki örnek kodu inceleyin:

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 yay için alıcı ve ayarlayıcı yöntemlerini tanımlar. Yay özelliklerini ayarlamak için yay kuvveti nesnesini almak veya özellikleri ayarlayabileceğiniz özel bir yay kuvveti oluşturmak önemlidir. Özel yay kuvveti oluşturma hakkında daha fazla bilgi için Özel bir yay kuvveti oluşturma bölümüne bakın.

İpucu: Tüm setter yöntemleri yay kuvveti nesnesini döndürdüğünden, setter yöntemlerini kullanırken bir yöntem zinciri oluşturabilirsiniz.

Sönümleme oranı

Sönümleme oranı, yay salınımının kademeli olarak azalmasını ifade eder. Sönümleme oranını kullanarak salınımların bir sıçrama hareketinden diğerine geçme hızını belirleyebilirsiniz. Bir yayı nemlendirmenin dört farklı yolu vardır:

  • Sönümleme oranı birden büyük olduğunda aşırı sönümleme meydana gelir. Nesnenin yavaşça bekleme pozisyonuna geri dönmesini sağlar.
  • Kritik sönümleme, sönümleme oranı bire eşit olduğunda gerçekleşir. Nesnenin en kısa sürede durağan konumuna dönmesini sağlar.
  • Düşük sönüm, sönümleme oranı birden az olduğunda gerçekleşir. Nesnenin, kalan pozisyonu geçerek birden fazla kez fazla çekim yapmasını ve daha sonra, yavaş yavaş dinlenme konumuna ulaşmasını sağlar.
  • Sönümsüz, sönümleme oranı sıfıra eşit olduğunda ortaya çıkar. Nesnenin sonsuza kadar sallanmasını sağlar.

Yayya sönümleme oranını 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 yayına eklemek istediğiniz sönümleme oranını iletin. Yöntem, sönümleme oranının ayarlandığı yay kuvveti nesnesini döndürür.

    Not: Sönümleme oranı, negatif olmayan bir sayı olmalıdır. Sönümleme oranını sıfıra ayarlarsanız yay hiçbir zaman durağan konuma ulaşmaz. Başka bir deyişle, sonsuza kadar dalgalanır.

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

Şekil 2: Yüksek hemen çıkma

Şekil 3: Orta düzeyde geri dönme

Şekil 4: Düşük geri dönme

Şekil 5: Hemen çıkma sorunu

Varsayılan sönüm oranı DAMPING_RATIO_MEDIUM_BOUNCY olarak ayarlandı.

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, yayın sabit konumda değilken takılı olan nesneye daha fazla kuvvet uygular. Yay sertliğini artırmak için aşağıdaki adımları uygulayın:

  1. Sertliği artırmak amacıyla yayı almak için getSpring() yöntemini çağırın.
  2. setStiffness() yöntemini çağırın ve ilkbahara eklemek istediğiniz sertlik değerini iletin. Yöntem, sertliğin ayarlandığı yay kuvveti nesnesini döndürür.

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

Sistemde aşağıdaki sertlik sabitleri bulunur:

Şekil 6: Yüksek sertlik

7. Şekil: Orta sertlik

Şekil 8: Düşük sertlik

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

Varsayılan sertlik düzeyi STIFFNESS_MEDIUM olarak ayarlandı.

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 bir yay kuvveti oluşturun

Varsayılan yay kuvvetini kullanmaya alternatif olarak özel bir yay kuvveti oluşturabilirsiniz. Özel yay kuvveti, aynı yay kuvveti örneğini birden fazla yay animasyonu arasında paylaşabilmenizi sağlar. Yay kuvvetini oluşturduktan sonra sönümleme oranı ve sertlik gibi özellikleri ayarlayabilirsiniz.

  1. Bir SpringForce nesnesi oluşturun.

    SpringForce force = new SpringForce();

  2. İlgili yöntemleri çağırarak özellikleri atayın. Dilerseniz 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

İlkbahar animasyonunu iki şekilde başlatabilirsiniz: start() yöntemini veya animateToFinalPosition() yöntemini çağırarak. Her iki yöntemin de ana iş parçacığında çağrılması gerekir.

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

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

Yöntem, yayının son konumunu güncellediğinden ve gerekirse animasyonu başlattığından animasyonun yönünü değiştirmek için istediğiniz zaman bu yöntemi çağırabilirsiniz. Örneğin, zincirleme bir yay animasyonunda bir görünümün animasyonu başka bir görünüme bağlıdır. Böyle bir animasyon için animateToFinalPosition() yöntemini kullanmak daha kolaydır. Bu yöntemi zincirleme bir ilkbahar animasyonunda kullandığınızda, bir sonraki güncellemek istediğiniz animasyon şu anda çalışıyorsa endişelenmenize gerek yoktur.

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

Zincirli ilkbahar demosu
Şekil 10. Zincirli ilkbahar demosu

animateToFinalPosition() yöntemini kullanmak için animateToFinalPosition() yöntemini çağırın ve yayının geri kalan konumunu geçirin. Ayrıca, setFinalPosition() yöntemini çağırarak ilkbaharın geri kalan konumunu da ayarlayabilirsiniz.

start() yöntemi, özellik değerini hemen başlangıç değerine ayarlamaz. Özellik değeri, çizim aktarımından önce gerçekleşen her animasyon titreşiminde değişir. Sonuç olarak, 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 et

Animasyonu iptal edebilir veya sonuna atlayabilirsiniz. Etkinliği iptal etmeniz veya sonuna atlamanız gereken ideal bir durum, bir kullanıcı etkileşimi animasyonun hemen sonlandırılmasını istediği durumdur. Bu durum, çoğunlukla kullanıcı 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, animasyonu son değere atlar ve ardından sonlandırır.

Animasyonu sonlandırabilmeniz için önce yayın durumunu kontrol etmeniz önemlidir. Durum sönümsüzse animasyon hiçbir zaman durağan konuma ulaşamaz. Yayının durumunu kontrol etmek için canSkipToEnd() yöntemini çağırın. Yay sönümlüyse yöntem true değerini, aksi takdirde false değerini döndürür.

Yayının durumunu öğrendikten sonra skipToEnd() veya cancel() yöntemini kullanarak animasyonu sonlandırabilirsiniz. cancel() yöntemi yalnızca ana iş parçacığında çağrılanmalıdır.

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