Gelişmiş animasyon örneği: Hareketler

Çalışırken göz önünde bulundurmamız gereken birkaç nokta var. ise dokunma etkinlikleri ve animasyonlarla, animasyonları kullanabilirsiniz. Öncelikle, devam eden bir animasyonu kesmemiz .

Aşağıdaki örnekte, ofset konumunu göstermek için bir Animatable kullanıyoruz. oluşturabilirsiniz. Dokunma etkinlikleri pointerInput kullanabilirsiniz. Yeni bir dokunma etkinliği algıladığımızda, hareket etmek için animateTo adını veririz. ofset değerini dokunun. Animasyon sırasında bir dokunma etkinliği meydana gelebilir Bu durumda, animateTo devam eden animasyonu kesintiye uğratır ve hızını korurken animasyonu yeni hedef konuma taşımaya kesilmiş animasyon.

@Composable
fun Gesture() {
    val offset = remember { Animatable(Offset(0f, 0f), Offset.VectorConverter) }
    Box(
        modifier = Modifier
            .fillMaxSize()
            .pointerInput(Unit) {
                coroutineScope {
                    while (true) {
                        // Detect a tap event and obtain its position.
                        awaitPointerEventScope {
                            val position = awaitFirstDown().position

                            launch {
                                // Animate to the tap position.
                                offset.animateTo(position)
                            }
                        }
                    }
                }
            }
    ) {
        Circle(modifier = Modifier.offset { offset.value.toIntOffset() })
    }
}

private fun Offset.toIntOffset() = IntOffset(x.roundToInt(), y.roundToInt())

Sık karşılaşılan diğer bir kalıp, animasyon değerlerini Google Etiket Yöneticisi'nde ve sürükleme gibi dokunma etkinliklerinden gelen trafiktir. Aşağıdaki örnekte "kaydırmak için kaydır"ı kapat" bir Modifier olarak uygulanır ( SwipeToDismiss composable). Öğenin yatay uzaklığı Animatable Bu API, hareket animasyonunda faydalı bir özelliğe sahiptir. Bu değeri, animasyonun yanı sıra dokunma etkinlikleri tarafından da değiştirilebilir. Bir dokunma etkinliğinde, Animatable işlemini stop yöntemiyle durdururuz. Böylece herhangi bir kesintiye uğrar.

Bir sürükleme etkinliği sırasında Animatable değerinisnapTo değer. Compose, fling için Sürükleme etkinliklerini kaydetmek ve hızı hesaplamak için VelocityTracker. Hız, ekibinizin hızla sıçrama animasyonu için doğrudan animateDecay öğesine aktarılacaktır. Kaydırmak istediğimizde uzaklık değerini orijinal konuma geri getirirseniz, hedef ofset değerini değeri animateTo yöntemiyle 0f olur.

fun Modifier.swipeToDismiss(
    onDismissed: () -> Unit
): Modifier = composed {
    val offsetX = remember { Animatable(0f) }
    pointerInput(Unit) {
        // Used to calculate fling decay.
        val decay = splineBasedDecay<Float>(this)
        // Use suspend functions for touch events and the Animatable.
        coroutineScope {
            while (true) {
                val velocityTracker = VelocityTracker()
                // Stop any ongoing animation.
                offsetX.stop()
                awaitPointerEventScope {
                    // Detect a touch down event.
                    val pointerId = awaitFirstDown().id

                    horizontalDrag(pointerId) { change ->
                        // Update the animation value with touch events.
                        launch {
                            offsetX.snapTo(
                                offsetX.value + change.positionChange().x
                            )
                        }
                        velocityTracker.addPosition(
                            change.uptimeMillis,
                            change.position
                        )
                    }
                }
                // No longer receiving touch events. Prepare the animation.
                val velocity = velocityTracker.calculateVelocity().x
                val targetOffsetX = decay.calculateTargetValue(
                    offsetX.value,
                    velocity
                )
                // The animation stops when it reaches the bounds.
                offsetX.updateBounds(
                    lowerBound = -size.width.toFloat(),
                    upperBound = size.width.toFloat()
                )
                launch {
                    if (targetOffsetX.absoluteValue <= size.width) {
                        // Not enough velocity; Slide back.
                        offsetX.animateTo(
                            targetValue = 0f,
                            initialVelocity = velocity
                        )
                    } else {
                        // The element was swiped away.
                        offsetX.animateDecay(velocity, decay)
                        onDismissed()
                    }
                }
            }
        }
    }
        .offset { IntOffset(offsetX.value.roundToInt(), 0) }
}

ziyaret edin.