Animasyonları özelleştir

Animasyon API'lerinin çoğu, davranışlarını özelleştirmek için genellikle parametreleri kabul eder.

Animasyonları AnimationSpec parametresiyle özelleştirme

Çoğu animasyon API'si, geliştiricilerin animasyon spesifikasyonlarını isteğe bağlı bir AnimationSpec parametresi ile özelleştirmesine olanak tanır.

val alpha: Float by animateFloatAsState(
    targetValue = if (enabled) 1f else 0.5f,
    // Configure the animation duration and easing.
    animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing),
    label = "alpha"
)

Farklı animasyon türleri oluşturmak için farklı AnimationSpec türleri vardır.

spring ile fizik tabanlı animasyon oluşturma

spring, başlangıç ve bitiş değerleri arasında fizik tabanlı bir animasyon oluşturur. 2 parametre alır: dampingRatio ve stiffness.

dampingRatio, yayın ne kadar esnek olacağını tanımlar. Varsayılan değer Spring.DampingRatioNoBouncy'tür.

Şekil 1. Farklı yay sönüm oranları ayarlama.

stiffness, yayının bitiş değerine doğru ne kadar hızlı hareket etmesi gerektiğini tanımlar. Varsayılan değer Spring.StiffnessMedium'tür.

Şekil 2. Farklı yay sertliği ayarlama

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = spring(
        dampingRatio = Spring.DampingRatioHighBouncy,
        stiffness = Spring.StiffnessMedium
    ),
    label = "spring spec"
)

spring, animasyonlar sırasında hedef değer değiştiğinde hızın sürekliliğini garanti ettiği için kesintileri süreye dayalı AnimationSpec türlerinden daha sorunsuz bir şekilde yönetebilir. spring, animate*AsState ve updateTransition gibi birçok animasyon API'si tarafından varsayılan AnimationSpec olarak kullanılır.

Örneğin, aşağıdaki kullanıcı dokunuşuyla çalışan animasyona bir spring yapılandırması uygularsak animasyon devam ederken kesinti yaptığımızda tween kullanılmasının spring kullanılması kadar sorunsuz yanıt vermediğini görebilirsiniz.

Şekil 3. Animasyon için tween ve spring özelliklerini ayarlama ve animasyonu kesintiye uğratma.

tween ile başlangıç ve bitiş değerleri arasında yavaşlatma eğrisi animasyonu

tween, bir yumuşatma eğrisi kullanarak belirtilen durationMillis üzerinde başlangıç ve bitiş değerleri arasında animasyon oluşturur. tween, iki değer arasında geçtiği için between kelimesinin kısaltmasıdır.

Animasyonun başlangıcını ertelemek için delayMillis değerini de belirtebilirsiniz.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = tween(
        durationMillis = 300,
        delayMillis = 50,
        easing = LinearOutSlowInEasing
    ),
    label = "tween delay"
)

Daha fazla bilgi için Easing (Yumuşatma) bölümüne bakın.

keyframes ile belirli zaman aralıklarında belirli değerlere animasyon

keyframes, animasyon süresinde farklı zaman damgalarında belirtilen anlık görüntü değerlerine göre animasyon oluşturur. Animasyon değeri, herhangi bir zamanda iki animasyon karesi değeri arasında ara değer olarak elde edilir. Bu ana karelerin her biri için, ara değer eğrisini belirlemek üzere Easing belirtilebilir.

0 ms ve süre anında değerleri belirtmek isteğe bağlıdır. Bu değerleri belirtmezseniz varsayılan olarak sırasıyla animasyonun başlangıç ve bitiş değerleri kullanılır.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = keyframes {
        durationMillis = 375
        0.0f at 0 using LinearOutSlowInEasing // for 0-15 ms
        0.2f at 15 using FastOutLinearInEasing // for 15-75 ms
        0.4f at 75 // ms
        0.4f at 225 // ms
    },
    label = "keyframe"
)

keyframesWithSplines ile animasyon kareleri arasında sorunsuz şekilde animasyon oluşturma

Değerler arasında geçiş yaparken düzgün bir eğri izleyen bir animasyon oluşturmak için keyframes animasyon özellikleri yerine keyframesWithSplines animasyon özelliklerini kullanabilirsiniz.

val offset by animateOffsetAsState(
    targetValue = Offset(300f, 300f),
    animationSpec = keyframesWithSpline {
        durationMillis = 6000
        Offset(0f, 0f) at 0
        Offset(150f, 200f) atFraction 0.5f
        Offset(0f, 100f) atFraction 0.7f
    }
)

Ekrandaki öğelerin 2D hareketi için özellikle spline tabanlı anahtar kareler kullanışlıdır.

Aşağıdaki videolarda, bir dairenin izlemesi gereken aynı x, y koordinatları verildiğinde keyframes ile keyframesWithSpline arasındaki farklar gösterilmektedir.

keyframes keyframesWithSplines

Gördüğünüz gibi, spline tabanlı animasyon kareleri, öğeler arasında sorunsuz bir şekilde animasyon oluşturmak için Bezier eğrileri kullandığından noktalar arasında daha yumuşak geçişler sunar. Bu özellik, hazır ayar animasyonu için yararlıdır. Ancak kullanıcı tarafından yönlendirilen noktalarla çalışıyorsanız noktalar arasında benzer bir akıcılık elde etmek için yay kullanmak tercih edilir. Çünkü bu noktalar kesintiye uğratılabilir.

repeatable ile animasyonu tekrarlama

repeatable, belirtilen iterasyon sayısına ulaşana kadar süreye dayalı bir animasyonu (tween veya keyframes gibi) tekrar tekrar çalıştırır. Animasyonun baştan (RepeatMode.Restart) mı yoksa sondan (RepeatMode.Reverse) mı tekrarlanacağını belirtmek için repeatMode parametresini iletebilirsiniz.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = repeatable(
        iterations = 3,
        animation = tween(durationMillis = 300),
        repeatMode = RepeatMode.Reverse
    ),
    label = "repeatable spec"
)

infiniteRepeatable ile bir animasyonu sonsuz olarak tekrarlama

infiniteRepeatable, repeatable'e benzer ancak sonsuz sayıda iterasyon için tekrarlanır.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = infiniteRepeatable(
        animation = tween(durationMillis = 300),
        repeatMode = RepeatMode.Reverse
    ),
    label = "infinite repeatable"
)

ComposeTestRule kullanan testlerde infiniteRepeatable kullanan animasyonlar çalıştırılmaz. Bileşen, her animasyonlu değerin ilk değeri kullanılarak oluşturulur.

snap ile hemen bitiş değerine sabitleme

snap, değeri hemen bitiş değerine geçiren özel bir AnimationSpec işlevidir. Animasyonun başlangıcını geciktirmek için delayMillis değerini belirtebilirsiniz.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = snap(delayMillis = 50),
    label = "snap spec"
)

Özel bir yumuşatma işlevi ayarlama

Süreye dayalı AnimationSpec işlemleri (tween veya keyframes gibi), bir animasyonun kesrini ayarlamak için Easing kullanır. Bu sayede, animasyonlu değer sabit bir hızda hareket etmek yerine hızlanır ve yavaşlar. Oranı, animasyonun mevcut noktasını belirten 0 (başlangıç) ile 1,0 (bitiş) arasında bir değerdir.

Easing, aslında 0 ile 1,0 arasında bir kesir değeri alan ve kayan nokta döndüren bir işlevdir. Döndürülen değer, aşırı veya yetersiz aşmayı temsil etmek için sınırın dışında olabilir. Aşağıdaki kod gibi özel bir Easing oluşturulabilir.

val CustomEasing = Easing { fraction -> fraction * fraction }

@Composable
fun EasingUsage() {
    val value by animateFloatAsState(
        targetValue = 1f,
        animationSpec = tween(
            durationMillis = 300,
            easing = CustomEasing
        ),
        label = "custom easing"
    )
    // ……
}

Oluşturma, çoğu kullanım alanını kapsayan çeşitli yerleşik Easing işlevleri sağlar. Senaryonuza bağlı olarak kolaylaştırmanın ne işe yaradığı hakkında daha fazla bilgi için Hız - Materyal Tasarım başlıklı makaleyi inceleyin.

  • FastOutSlowInEasing
  • LinearOutSlowInEasing
  • FastOutLinearEasing
  • LinearEasing
  • CubicBezierEasing
  • Diğerlerini göster

AnimationVector ile dönüşüm yaparak özel veri türlerini canlandırma

Compose animasyon API'lerinin çoğu, varsayılan olarak animasyon değerleri olarak Float, Color, Dp ve diğer temel veri türlerini destekler ancak bazen özel olanlar da dahil olmak üzere diğer veri türlerini animasyonlu hale getirmeniz gerekir. Animasyon sırasında, animasyonlu tüm değerler AnimationVector olarak gösterilir. Değer, temel animasyon sisteminin bunları tek tip şekilde işleyebilmesi için ilgili bir TwoWayConverter tarafından AnimationVector'e dönüştürülür ve bunun tersi de geçerlidir. Örneğin, Int tek bir kayan noktalı değer içeren bir AnimationVector1D olarak temsil edilir. Int için TwoWayConverter şu şekilde görünür:

val IntToVector: TwoWayConverter<Int, AnimationVector1D> =
    TwoWayConverter({ AnimationVector1D(it.toFloat()) }, { it.value.toInt() })

Color temel olarak kırmızı, yeşil, mavi ve alfa olmak üzere 4 değerden oluşan bir kümedir. Bu nedenle Color, 4 kayan nokta değeri içeren bir AnimationVector4D değerine dönüştürülür. Bu şekilde, animasyonlarda kullanılan her veri türü, boyutuna bağlı olarak AnimationVector1D, AnimationVector2D, AnimationVector3D veya AnimationVector4D olarak dönüştürülür. Bu sayede nesnenin farklı bileşenleri, her biri kendi hız izlemesine sahip olacak şekilde bağımsız olarak animasyonlu hale getirilebilir. Temel veri türleri için yerleşik dönüştürücülere Color.VectorConverter veya Dp.VectorConverter gibi dönüştürücüler kullanılarak erişilebilir.

Animasyonlu değer olarak yeni bir veri türü için destek eklemek istediğinizde kendi TwoWayConverter'inizi oluşturabilir ve API'ye gönderebilirsiniz. Örneğin, özel veri türünüzü animasyonlu hale getirmek için animateValueAsState öğesini şu şekilde kullanabilirsiniz:

data class MySize(val width: Dp, val height: Dp)

@Composable
fun MyAnimation(targetSize: MySize) {
    val animSize: MySize by animateValueAsState(
        targetSize,
        TwoWayConverter(
            convertToVector = { size: MySize ->
                // Extract a float value from each of the `Dp` fields.
                AnimationVector2D(size.width.value, size.height.value)
            },
            convertFromVector = { vector: AnimationVector2D ->
                MySize(vector.v1.dp, vector.v2.dp)
            }
        ),
        label = "size"
    )
}

Aşağıdaki listede bazı yerleşik VectorConverter'ler verilmiştir: