Animasyonları özelleştir

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

AnimationSpec parametresiyle animasyonları özelleştirme

Çoğu animasyon API'si, geliştiricilerin isteğe bağlı AnimationSpec parametresiyle animasyon spesifikasyonlarını ö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. Bu işlev 2 parametre alır: dampingRatio ve stiffness.

dampingRatio, yayın ne kadar esnek olması gerektiğini tanımlar. Varsayılan değer: Spring.DampingRatioNoBouncy.

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

stiffness, yayın hareketinin bitiş değerine ne kadar hızlı ulaşacağını tanımlar. Varsayılan değer Spring.StiffnessMedium'dı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ı kesintisiz hale getirdiği için süreye dayalı AnimationSpec türlerine kıyasla kesintileri 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, kullanıcı dokunuşuyla yönlendirilen aşağıdaki animasyona spring yapılandırması uygularsak animasyon ilerlerken kesintiye uğradığında tween kullanmanın spring kullanmak 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 yavaşlatma eğrisi kullanarak başlangıç ve bitiş değerleri arasında animasyon oluşturma

tween, belirtilen durationMillis süre boyunca başlangıç ve bitiş değerleri arasında yavaşlatma eğrisi kullanarak animasyon oluşturur. tween, iki değerin arasında olduğu için between (arasında) 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 (Kolaylaştırma) bölümüne bakın.

keyframes ile belirli zamanlarda belirli değerlere animasyon uygulama

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

Değerlerin 0 ms'de ve süre boyunca belirtilmesi isteğe bağlıdır. Bu değerleri belirtmezseniz sırasıyla animasyonun başlangıç ve bitiş değerleri varsayılan olarak 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 bir şekilde animasyon oluşturun

Değerler arasında geçiş yaparken düzgün bir eğriyi takip eden bir animasyon oluşturmak için keyframes animasyon özellikleri yerine keyframesWithSplines 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
    }
)

Eğri tabanlı anahtar kareler, ekrandaki öğelerin 2 boyutlu hareketi için özellikle yararlıdır.

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

keyframes keyframesWithSplines

Gördüğünüz gibi, spline tabanlı anahtar kareler, öğeler arasında sorunsuz bir şekilde animasyon oluşturmak için Bezier eğrilerini kullandığından noktalar arasında daha yumuşak geçişler sunar. Bu özellik, önceden ayarlanmış bir animasyon için kullanışlıdır. Ancak kullanıcı tarafından oluşturulan noktalarla çalışıyorsanız kesintiye uğratılabildikleri için noktalar arasında benzer bir akıcılık elde etmek için yayları kullanmanız tercih edilir.

repeatable ile animasyonu tekrarlama

repeatable, belirtilen yineleme sayısına ulaşana kadar süreyi temel alan bir animasyonu (ör. tween veya keyframes) tekrar tekrar çalıştırır. Animasyonun baştan (RepeatMode.Restart) veya sondan (RepeatMode.Reverse) başlayarak tekrarlanıp tekrarlanmayacağı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 animasyonu sonsuza kadar tekrarlama

infiniteRepeatable, repeatable işlevine benzer ancak sonsuz sayıda tekrarlanır.

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

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

snap ile hemen bitiş değerine tutturun

snap, değeri hemen bitiş değerine değiştiren özel bir AnimationSpec'dir. 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 kolaylaştırma işlevi ayarlama

Süreye dayalı AnimationSpec işlemleri (ör. tween veya keyframes), animasyonun kesirini ayarlamak için Easing kullanır. Bu sayede, animasyonlu değer sabit bir hızda hareket etmek yerine hızlanıp yavaşlayabilir. Kesir, animasyondaki mevcut noktayı gösteren 0 (başlangıç) ile 1,0 (bitiş) arasındaki bir değerdir.

Easing, aslında 0 ile 1,0 arasında bir kesir değeri alan ve kayan nokta değeri döndüren bir işlevdir. Döndürülen değer, aşmayı veya eksikliği temsil etmek için sınırın dışında olabilir. Aşağıdaki kodda olduğu 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"
    )
    // ……
}

Compose, çoğu kullanım alanını kapsayan çeşitli yerleşik Easing işlevleri sunar. Senaryonuza bağlı olarak hangi yumuşatma işlevini kullanacağınız 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

Özel veri türlerini AnimationVector biçimine dönüştürerek ve bu biçimden dönüştürerek animasyon ekleyin.

Çoğu Compose animasyon API'si, varsayılan olarak animasyon değerleri için Float, Color, Dp ve diğer temel veri türlerini destekler ancak bazen özel olanlar da dahil olmak üzere diğer veri türlerini de canlandırmanız gerekir. Animasyon sırasında, animasyonlu 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'ya 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 gösterilir. Int için TwoWayConverter şu şekilde görünür:

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

Color, temelde 4 değerden (kırmızı, yeşil, mavi ve alfa) oluşan bir kümedir. Bu nedenle, Color, 4 kayan nokta değeri içeren bir AnimationVector4D öğesine 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 bağımsız olarak ve her biri kendi hız takibiyle animasyonlandırılabilir. 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.

Animasyon değeri olarak yeni bir veri türü için destek eklemek istediğinizde kendi TwoWayConverter öğenizi oluşturup API'ye sağlayabilirsiniz. Örneğin, animateValueAsState kullanarak özel veri türünüzü aşağıdaki gibi canlandırabilirsiniz:

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: