Compose bietet integrierte Composeables und Modifikatoren für gängige Anwendungsfälle von Animationen.
Eingebaute animierte Composeables
Mit AnimatedVisibility
das Erscheinen und Verschwinden animieren
Mit dem AnimatedVisibility
-Kompositelement wird das Ein- und Ausblenden des Inhalts animiert.
var visible by remember { mutableStateOf(true) } // Animated visibility will eventually remove the item from the composition once the animation has finished. AnimatedVisibility(visible) { // your composable here // ... }
Standardmäßig werden die Inhalte eingeblendet, indem sie eingeblendet und maximiert werden, und ausgeblendet, indem sie ausgeblendet und minimiert werden. Der Übergang kann angepasst werden, indem EnterTransition
und ExitTransition
angegeben werden.
var visible by remember { mutableStateOf(true) } val density = LocalDensity.current AnimatedVisibility( visible = visible, enter = slideInVertically { // Slide in from 40 dp from the top. with(density) { -40.dp.roundToPx() } } + expandVertically( // Expand from the top. expandFrom = Alignment.Top ) + fadeIn( // Fade in with the initial alpha of 0.3f. initialAlpha = 0.3f ), exit = slideOutVertically() + shrinkVertically() + fadeOut() ) { Text( "Hello", Modifier .fillMaxWidth() .height(200.dp) ) }
Wie im Beispiel oben zu sehen, können Sie mehrere EnterTransition
- oder ExitTransition
-Objekte mit einem +
-Operator kombinieren. Für jeden Operator können optionale Parameter verwendet werden, um das Verhalten anzupassen. Weitere Informationen finden Sie in den Referenzen.
Beispiele für EnterTransition
und ExitTransition
AnimatedVisibility
bietet auch eine Variante, die einen MutableTransitionState
annimmt. So können Sie eine Animation auslösen, sobald die AnimatedVisibility
dem Kompositionbaum hinzugefügt wird. Es ist auch nützlich, den Animationsstatus zu beobachten.
// Create a MutableTransitionState<Boolean> for the AnimatedVisibility. val state = remember { MutableTransitionState(false).apply { // Start the animation immediately. targetState = true } } Column { AnimatedVisibility(visibleState = state) { Text(text = "Hello, world!") } // Use the MutableTransitionState to know the current animation state // of the AnimatedVisibility. Text( text = when { state.isIdle && state.currentState -> "Visible" !state.isIdle && state.currentState -> "Disappearing" state.isIdle && !state.currentState -> "Invisible" else -> "Appearing" } ) }
Ein- und Ausblenden für Kinder animieren
Für Inhalte innerhalb von AnimatedVisibility
(direkte oder indirekte untergeordnete Elemente) kann der Modifikator animateEnterExit
verwendet werden, um für jedes Element ein anderes Animationsverhalten festzulegen. Der visuelle Effekt für jedes dieser untergeordneten Elemente ist eine Kombination aus den im AnimatedVisibility
-Composit angegebenen Animationen und den eigenen Ein- und Ausblendungsanimationen des untergeordneten Elements.
var visible by remember { mutableStateOf(true) } AnimatedVisibility( visible = visible, enter = fadeIn(), exit = fadeOut() ) { // Fade in/out the background and the foreground. Box( Modifier .fillMaxSize() .background(Color.DarkGray) ) { Box( Modifier .align(Alignment.Center) .animateEnterExit( // Slide in/out the inner box. enter = slideInVertically(), exit = slideOutVertically() ) .sizeIn(minWidth = 256.dp, minHeight = 64.dp) .background(Color.Red) ) { // Content of the notification… } } }
In einigen Fällen möchten Sie möglicherweise, dass AnimatedVisibility
keine Animationen anwendet, damit Kinder jeweils eigene Animationen von animateEnterExit
erhalten. Geben Sie dazu EnterTransition.None
und ExitTransition.None
für die AnimatedVisibility
-Komponente an.
Benutzerdefinierte Animation hinzufügen
Wenn du über die integrierten Ein- und Ausblendungsanimationen hinaus benutzerdefinierte Animationen hinzufügen möchtest, greife über das Attribut transition
im Inhalts-Lambda für AnimatedVisibility
auf die zugrunde liegende Transition
-Instanz zu. Alle der Transition-Instanz hinzugefügten Animationszustände werden gleichzeitig mit den Ein- und Ausblendungsanimationen von AnimatedVisibility
ausgeführt. AnimatedVisibility
wartet, bis alle Animationen im Transition
abgeschlossen sind, bevor der Inhalt entfernt wird.
Bei unabhängig von Transition
erstellten Beendigungsanimationen (z. B. mit animate*AsState
) kann AnimatedVisibility
diese nicht berücksichtigen und entfernt die zusammengesetzten Inhalte möglicherweise, bevor sie fertig sind.
var visible by remember { mutableStateOf(true) } AnimatedVisibility( visible = visible, enter = fadeIn(), exit = fadeOut() ) { // this: AnimatedVisibilityScope // Use AnimatedVisibilityScope#transition to add a custom animation // to the AnimatedVisibility. val background by transition.animateColor(label = "color") { state -> if (state == EnterExitState.Visible) Color.Blue else Color.Gray } Box( modifier = Modifier .size(128.dp) .background(background) ) }
Weitere Informationen zu Transition
finden Sie unter updateTransition.
Mit AnimatedContent
basierend auf dem Zielstatus animieren
Das AnimatedContent
-Kompositelement animiert seinen Inhalt, wenn er sich basierend auf einem Zielstatus ändert.
Row { var count by remember { mutableIntStateOf(0) } Button(onClick = { count++ }) { Text("Add") } AnimatedContent( targetState = count, label = "animated content" ) { targetCount -> // Make sure to use `targetCount`, not `count`. Text(text = "Count: $targetCount") } }
Sie sollten den Lambda-Parameter immer verwenden und in den Inhalt einbinden. Die API verwendet diesen Wert als Schlüssel, um die aktuell angezeigten Inhalte zu identifizieren.
Standardmäßig wird der ursprüngliche Inhalt ausgeblendet und dann der Zielinhalt eingeblendet. Dieses Verhalten wird als Wechsel per Überblendung bezeichnet. Sie können dieses Animationsverhalten anpassen, indem Sie dem Parameter transitionSpec
ein ContentTransform
-Objekt angeben. Sie können ContentTransform
erstellen, indem Sie mithilfe der Infixfunktion with
einen EnterTransition
mit einem ExitTransition
kombinieren. Sie können SizeTransform
auf den ContentTransform
anwenden, indem Sie ihn mit der Infix-Funktion using
verknüpfen.
AnimatedContent( targetState = count, transitionSpec = { // Compare the incoming number with the previous number. if (targetState > initialState) { // If the target number is larger, it slides up and fades in // while the initial (smaller) number slides up and fades out. slideInVertically { height -> height } + fadeIn() togetherWith slideOutVertically { height -> -height } + fadeOut() } else { // If the target number is smaller, it slides down and fades in // while the initial number slides down and fades out. slideInVertically { height -> -height } + fadeIn() togetherWith slideOutVertically { height -> height } + fadeOut() }.using( // Disable clipping since the faded slide-in/out should // be displayed out of bounds. SizeTransform(clip = false) ) }, label = "animated content" ) { targetCount -> Text(text = "$targetCount") }
Mit EnterTransition
wird festgelegt, wie die Zielinhalte erscheinen sollen, und mit ExitTransition
, wie die ursprünglichen Inhalte verschwinden sollen. Zusätzlich zu allen EnterTransition
- und ExitTransition
-Funktionen, die für AnimatedVisibility
verfügbar sind, bietet AnimatedContent
slideIntoContainer
und slideOutOfContainer
.
Dies sind praktische Alternativen zu slideInHorizontally/Vertically
und slideOutHorizontally/Vertically
, bei denen der Folienabstand basierend auf der Größe des ursprünglichen Inhalts und des Zielinhalts des AnimatedContent
-Inhalts berechnet wird.
Mit SizeTransform
wird festgelegt, wie die Größe zwischen dem ursprünglichen und dem Zielinhalt animiert werden soll. Beim Erstellen der Animation haben Sie Zugriff auf die Anfangs- und die Zielgröße. Mit SizeTransform
wird auch festgelegt, ob die Inhalte während der Animationen auf die Größe der Komponente zugeschnitten werden sollen.
var expanded by remember { mutableStateOf(false) } Surface( color = MaterialTheme.colorScheme.primary, onClick = { expanded = !expanded } ) { AnimatedContent( targetState = expanded, transitionSpec = { fadeIn(animationSpec = tween(150, 150)) togetherWith fadeOut(animationSpec = tween(150)) using SizeTransform { initialSize, targetSize -> if (targetState) { keyframes { // Expand horizontally first. IntSize(targetSize.width, initialSize.height) at 150 durationMillis = 300 } } else { keyframes { // Shrink vertically first. IntSize(initialSize.width, targetSize.height) at 150 durationMillis = 300 } } } }, label = "size transform" ) { targetExpanded -> if (targetExpanded) { Expanded() } else { ContentIcon() } } }
Übergänge für das Ein- und Ausblenden von Kindern animieren
Wie bei AnimatedVisibility
ist der Modifikator animateEnterExit
im Inhalts-Lambda von AnimatedContent
verfügbar. So können Sie EnterAnimation
und ExitAnimation
auf jedes direkte oder indirekte untergeordnete Element einzeln anwenden.
Benutzerdefinierte Animation hinzufügen
Wie AnimatedVisibility
ist auch das Feld transition
im Inhaltslambda von AnimatedContent
verfügbar. Damit können Sie einen benutzerdefinierten Animationseffekt erstellen, der gleichzeitig mit dem Übergang AnimatedContent
ausgeführt wird. Weitere Informationen finden Sie unter updateTransition.
Mit Crossfade
zwischen zwei Layouts animieren
Crossfade
animiert zwischen zwei Layouts mit einer Crossfade-Animation. Durch Umschalten des an den current
-Parameter übergebenen Werts wird der Inhalt mit einer Crossfade-Animation gewechselt.
var currentPage by remember { mutableStateOf("A") } Crossfade(targetState = currentPage, label = "cross fade") { screen -> when (screen) { "A" -> Text("Page A") "B" -> Text("Page B") } }
Integrierte Animationsmodifikatoren
Größe von Elementen mit animateContentSize
animieren
Mit dem Modifikator animateContentSize
wird eine Größenänderung animiert.
var expanded by remember { mutableStateOf(false) } Box( modifier = Modifier .background(colorBlue) .animateContentSize() .height(if (expanded) 400.dp else 200.dp) .fillMaxWidth() .clickable( interactionSource = remember { MutableInteractionSource() }, indication = null ) { expanded = !expanded } ) { }
Listenelement-Animationen
Wenn Sie die Neuanordnung von Elementen in einer Lazy-Liste oder einem Lazy-Raster animieren möchten, lesen Sie die Dokumentation zur Lazy-Layout-Elementanimation.
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Wertbezogene Animationen
- Animationen in Compose
- Unterstützung von Animationstools {:#tooling}