Bei der Arbeit mit Google Workspace for Education mit Touch-Ereignissen und Animationen arbeiten, Animationen zu erstellen. Zunächst müssen wir möglicherweise eine laufende Animation unterbrechen, wenn Touch-Ereignisse beginnen, da eine Nutzerinteraktion die höchste Priorität haben sollte.
Im folgenden Beispiel verwenden wir ein Animatable
, um den Versatz der Position
Kreiskomponente. Touch-Ereignisse werden mit dem Modifikator pointerInput
verarbeitet. Wird ein neues Tippereignis erkannt, rufen wir animateTo
auf, um die
Versatzwert auf die Tippposition setzen. Ein Tipp-Ereignis kann auch während der Animation auftreten. In diesem Fall unterbricht animateTo
die laufende Animation und startet die Animation zur neuen Zielposition, wobei die Geschwindigkeit der unterbrochenen Animation beibehalten wird.
@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())
Ein weiteres häufiges Muster ist, dass wir Animationswerte mit Werten aus Touch-Ereignissen synchronisieren müssen, z. B. Ziehen. Im folgenden Beispiel wird „Wischen zum Schließen“ als Modifier
implementiert, anstatt die SwipeToDismiss
-Komposition zu verwenden. Der horizontale Offset des Elements wird als Animatable
dargestellt. Diese API hat eine Eigenschaft, die für die Bewegungsanimation nützlich ist. Das
kann durch Touch-Ereignisse und die Animation geändert werden. Wenn wir ein Touchdown-Ereignis erhalten, stoppen wir die Animatable
mit der Methode stop
, damit laufende Animationen abgefangen werden.
Während eines Drag-Ereignisses verwenden wir snapTo
, um den Animatable
-Wert mit dem
Wert, der aus Touch-Ereignissen berechnet wurde. Mit der Funktion „Schreiben“
VelocityTracker
, um Drag-Ereignisse aufzuzeichnen und die Geschwindigkeit zu berechnen. Die Geschwindigkeit kann
für die Fling-Animation direkt in animateDecay
eingespeist werden. Wenn wir den Offsetwert wieder in die ursprüngliche Position verschieben möchten, geben wir mit der Methode animateTo
den Zieloffsetwert 0f
an.
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) } }
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Wertbezogene Animationen
- Ziehen, wischen und schleudern
- Touch-Gesten