Yay fiziğini kullanarak hareketi canlandırma

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

Fiziğe dayalı hareket kuvvet ile yönetilir. Yay kuvveti, etkileşimi ve hareketi yönlendiren böyle bir kuvvettir. Yay kuvveti şu özelliklere sahiptir: sönümleme ve sertlik. Yaya dayalı bir animasyonda değer ve hız, her kareye uygulanan yay kuvvetine göre hesaplanır.

Uygulamanızdaki animasyonların yalnızca bir yönde yavaşlamasını istiyorsanız bunun yerine sürtünmeyi temel alan bir hızlıca kaydırma animasyonu kullanmayı düşünün.

Bir baharın 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ştirmenizi sağlar. Animasyon başlar başlamaz, yay kuvveti, animasyon değerini ve her karedeki hızı günceller. Yayın kuvveti dengeye ulaşana kadar animasyon 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 ancak tanıdık bir kuvvet ile orijinal yerine geri çekilir.

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

İlkbahar yayını
Şekil 1. İlkbahar yayını etkisi

İlkbahar animasyonu oluştur

Uygulamanız için bir yay animasyonu oluşturmaya yönelik genel adımlar aşağıdaki gibidir:

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

Destek kitaplığı 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 için build.gradle dosyasını açın.
  2. dependencies bölümüne destek kitaplığını ekleyin.

    Eski

            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ında Dynamicanimation hakkındaki bilgilere bakın.

İlkbahar animasyonu oluştur

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

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

Yayına 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ükseklikten delta olarak nerede konumlanacağını kontrol eder.
  • ROTATION, ROTATION_X ve ROTATION_Y: Bu özellikler, pivot noktasının çevresindeki 2D (rotation özelliği) ve 3D yöndeki 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 gösterir. Ayrıca sayfanın ne kadar kaydırıldığına ilişkin konumu da belirtir.
  • SCALE_X ve SCALE_Y: Bu özellikler, bir görünümün pivot noktası etrafındaki 2D ölçeklendirmeyi kontrol eder.
  • X, Y ve Z: Bunlar, görünümün container'ındaki son konumunu tanımlamak için kullanılan temel yardımcı program özellikleridir.

Dinleyicileri 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 durumlarda animasyondaki güncellemeleri dinler.

AnimasyonGüncelleme Listeleyicisi

Zincirli bir animasyon oluşturmak için birden fazla görünümü canlandırmak istediğinizde OnAnimationUpdateListener öğesini, geçerli görünümün özelliğinde her değişiklik olduğunda geri çağrı alacak şekilde ayarlayabilirsiniz. Geri çağırma, diğer görünümü, geçerli görünümün mülkünde yapılan değişikliğe dayalı olarak ilkbahar konumunu güncellemesi için bilgilendirir. İşleyiciyi 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şleyicisi yalnızca animasyon değeri değişikliklerinde kare başına güncellemeye ihtiyaç duyduğunuzda kaydedilmelidir. Güncelleme işleyici, animasyonun ayrı bir iş parçacığında çalıştırılmasını önler.

  2. Arayana, geçerli nesnedeki değişikliği bildirmek için onAnimationUpdate() yöntemini geçersiz kılın. Aşağıdaki örnek kodda OnAnimationUpdateListener ürününün genel kullanımı gösterilmektedir.

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);
    }
});

OnAnimasyonEndListener'ı

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

  1. addEndListener() yöntemini çağırın ve işleyiciyi animasyona ekleyin.
  2. 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 çağırmaları ve animasyon sonu 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 nesne ö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. Ayrıca, alfa gibi (0 ile 1 arasında) doğal bir aralığa sahip olan özellikleri canlandıracağınız takdirde 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 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şlangıcında animasyon özelliğinin değişme 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 saniye başına dp olarak tanımlamanız ve daha sonra bunu saniyede piksel sayısına dönüştürmenizi öneririz. Değerin saniye başına dp cinsinden tanımlanması, hızın yoğunluk ve form faktörlerinden bağımsız olmasını sağlar. Değeri saniye başına piksele dönüştürme hakkında daha fazla bilgi için Saniyedeki dp değerini saniyedeki piksel sayısına dönüştürme bölümüne bakın.

Hızı ayarlamak için setStartVelocity() yöntemini çağırın ve hızı saniye başına piksel 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 değerini saniyedeki piksel sayısına 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 dp/saniye cinsinden sağlayın ve ardından saniyedeki piksel sayısına dönüştürün. Dönüştürmek için TypedValue sınıfındaki applyDimension() yöntemini 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 yay özelliklerinin her biri için alıcı ve belirleyici 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 yay kuvveti oluşturma bölümüne bakın.

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

Nemlendirme oranı

Sönümleme oranı, yay salınımındaki kademeli azalmayı ifade eder. Sönümleme oranını kullanarak salınımların bir sıçramadan diğerine ne hızda azaldığını tanımlayabilirsiniz. Yayı nemlendirmenin dört farklı yolu vardır:

  • Aşırı sönümleme, sönümleme oranı birden büyük olduğunda ortaya çıkar. Nesnenin yavaşça hareketsiz konuma 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 durgun konumuna dönmesini sağlar.
  • Sönümleme, sönümleme oranı birden az olduğunda meydana gelir. Kalan konumu geçerek nesnenin birden fazla kez aşınmasını sağlar, ardından yavaş yavaş kalan konuma ulaşır.
  • Sönümleme, sönümleme oranı sıfıra eşit olduğunda gerçekleşir. Nesnenin sonsuza kadar salınmasını sağlar.

Sönüm oranını yayına eklemek için aşağıdaki adımları uygulayın:

  1. Sönüm oranını eklemek üzere yayını almak için 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üm oranını sıfır olarak ayarlarsanız yay hiçbir zaman sabit konuma ulaşmaz. Diğer bir deyişle, sonsuza kadar dalgalanır.

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

Şekil 2: Yüksek hemen çıkma

Şekil 3: Orta düzeyde hemen çıkma

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

Şekil 5: Hemen çıkma yok

Varsayılan sönümleme 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 kuvvetini ölçen yayın sabitini tanımlar. Sert bir yay, yayın hareketsiz konumda değilken eklenen nesneye daha fazla kuvvet uygular. Yaya sertliği eklemek için aşağıdaki adımları uygulayın:

  1. Sertliği eklemek amacıyla yayını almak için getSpring() yöntemini çağırın.
  2. setStiffness() yöntemini çağırın ve yaya 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 kullanılabilir:

Şekil 6: Yüksek sertlik

7. Şekil: Orta düzeyde sertlik

8. Şekil: Düşük sertlik

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

Varsayılan sertlik 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 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 animasyonunda paylaşmanıza olanak tanır. 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. Ayrıca yöntem zinciri 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 başlatmanın iki yolu vardır: start() 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 yerine getirir:

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

Yöntem, ilkbaharın son konumunu güncellediğinden ve gerekirse animasyonu başlattığından, animasyonun seyrini değiştirmek için bu yöntemi istediğiniz zaman çağırabilirsiniz. Örneğin, zincirleme ilkbahar 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önteminin kullanılması daha kolaydır. Bu yöntemi zincirli ilkbahar animasyonunda kullandığınızda, güncellemek istediğiniz bir sonraki animasyon çalışıyorsa endişelenmenize gerek yoktur.

Şekil 10'da, bir görünümün animasyonu başka bir görünüme bağlı olduğu zincirli ilkbahar animasyonu gösterilmiştir.

Zincirli ilkbahar demosu
Şekil 10. Zincirli ilkbahar demosu

animateToFinalPosition() yöntemini kullanmak için animateToFinalPosition() yöntemini çağırıp yayın geri kalan konumunu iletin. setFinalPosition() yöntemini çağırarak yayın yerinin geri kalanını da ayarlayabilirsiniz.

start() yöntemi, özellik değerini başlangıç değeri olarak hemen ayarlamaz. Özellik değeri, çizim geçişi öncesinde gerçekleşen her animasyon nabzında değişir. Sonuç olarak değişiklikler, değerler hemen ayarlanmış gibi 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 animasyonun sonuna atlayabilirsiniz. Bir kullanıcı etkileşiminin animasyonun hemen sonlandırılmasını talep etmesi halinde, amasyonu iptal etmeniz veya sonuna atlamanız gereken ideal bir durum söz konusudur. Bu durum çoğunlukla kullanıcı uygulamadan aniden çıkarsa veya görünüm görünmez hale gelir.

Animasyonu sonlandırmak için kullanabileceğiniz iki yöntem vardır. cancel() yöntemi, animasyonu olduğu değerde sonlandırır. skipToEnd() yöntemi, animasyonu nihai değere atlar ve daha sonra sonlandırır.

Animasyonu sonlandırmadan önce ilk olarak yayın durumunu kontrol etmeniz önemlidir. Durum sönümlenmemişse animasyon hiçbir zaman kalan konuma erişemez. Yayının durumunu kontrol etmek için canSkipToEnd() yöntemini çağırın. Yay sönümlenirse yöntem true değerini döndürür; aksi takdirde false değerini döndürür.

Yayının durumunu öğrendikten sonra, skipToEnd() veya cancel() yöntemini kullanarak bir 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 atlamaya neden olur.