Compose verfügt über integrierte zusammensetzbare Funktionen und Modifikatoren für gängige Anwendungsfälle in der Animation.
Integrierte animierte zusammensetzbare Funktionen
Aussehen und Verschwinden mit AnimatedVisibility
animieren
In der zusammensetzbaren Funktion AnimatedVisibility
werden die Darstellung und das Verschwinden ihres 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 // ... }
Der Inhalt wird standardmäßig eingeblendet und eingeblendet, wenn er eingeblendet wird, und wieder ausgeblendet, wenn er ausgeblendet wird. Der Übergang kann durch Angabe von EnterTransition
und ExitTransition
angepasst 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 Sie im obigen Beispiel sehen können, können Sie mehrere EnterTransition
- oder ExitTransition
-Objekte mit einem +
-Operator kombinieren. Jedes Objekt akzeptiert optionale Parameter, um sein Verhalten anzupassen. Weitere Informationen finden Sie in den Referenzen.
Beispiele für EnterTransition
und ExitTransition
AnimatedVisibility
bietet auch eine Variante mit MutableTransitionState
an. So kannst du eine Animation auslösen, sobald AnimatedVisibility
dem Kompositionsbaum hinzugefügt wird. Sie ist auch nützlich, um
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 Ausgang für Kinder animieren
Für Inhalte in AnimatedVisibility
(direkte oder indirekte untergeordnete Elemente) kann mit dem Modifikator animateEnterExit
für jeden ein anderes Animationsverhalten angegeben werden. Der visuelle Effekt für jedes dieser untergeordneten Elemente ist eine Kombination aus den Animationen, die in der zusammensetzbaren AnimatedVisibility
-Funktion angegeben sind, und den eigenen Eingabe- und Beenden-Animationen 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 kann es sinnvoll sein, dass AnimatedVisibility
überhaupt keine Animationen anwendet, sodass untergeordnete Elemente jeweils eigene Animationen von animateEnterExit
haben können. Dazu geben Sie EnterTransition.None
und ExitTransition.None
bei der zusammensetzbaren Funktion AnimatedVisibility
an.
Benutzerdefinierte Animation hinzufügen
Wenn Sie über die integrierten Animationen zum Ein- und Beenden hinaus benutzerdefinierte Animationseffekte hinzufügen möchten, greifen Sie über das Attribut transition
innerhalb der Inhalts-Lambda für AnimatedVisibility
auf die zugrunde liegende Transition
-Instanz zu. Alle Animationsstatus, die der Übergangsinstanz hinzugefügt werden, werden gleichzeitig mit den Eingabe- und Exit-Animationen von AnimatedVisibility
ausgeführt. AnimatedVisibility
wartet, bis alle Animationen im Transition
beendet sind, bevor der Inhalt entfernt wird.
Bei Exit-Animationen, die unabhängig von Transition
erstellt wurden (z. B. mit animate*AsState
), kann AnimatedVisibility
diese nicht berücksichtigen und daher möglicherweise die zusammensetzbaren Inhalte entfernen, 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
Die zusammensetzbare Funktion AnimatedContent
animiert den Inhalt, wenn er sich je nach Zielstatus ändert.
Row { var count by remember { mutableStateOf(0) } Button(onClick = { count++ }) { Text("Add") } AnimatedContent(targetState = count) { targetCount -> // Make sure to use `targetCount`, not `count`. Text(text = "Count: $targetCount") } }
Beachte, dass du immer den Lambda-Parameter verwenden solltest und ihn im Inhalt widerspiegelt. 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 ausgeblendet. Dieses Verhalten wird als Überblenden bezeichnet. Sie können dieses Animationsverhalten anpassen, indem Sie ein ContentTransform
-Objekt für den Parameter transitionSpec
angeben. Sie können ContentTransform
erstellen, indem Sie mithilfe der Infix-Funktion with
ein EnterTransition
mit einem ExitTransition
kombinieren. Sie können SizeTransform
auf ContentTransform
anwenden, indem Sie es mit der Infix-Funktion using
anhängen.
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() with 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() with slideOutVertically { height -> height } + fadeOut() }.using( // Disable clipping since the faded slide-in/out should // be displayed out of bounds. SizeTransform(clip = false) ) } ) { targetCount -> Text(text = "$targetCount") }
Mit EnterTransition
wird definiert, wie der Zielinhalt angezeigt werden soll, und mit ExitTransition
, wie der ursprüngliche Inhalt ausgeblendet werden soll. 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
. Sie berechnen die Entfernung für die Folie anhand der Größe des ursprünglichen Inhalts und des Zielinhalts des AnimatedContent
-Inhalts.
Mit SizeTransform
wird definiert, wie die Größe zwischen dem Anfangs- und dem Zielinhalt animiert werden soll. Beim Erstellen der Animation haben Sie Zugriff auf die Anfangs- und die Zielgröße. Mit SizeTransform
wird auch gesteuert, ob der Inhalt bei Animationen auf die Komponentengröße zugeschnitten werden soll.
var expanded by remember { mutableStateOf(false) } Surface( color = MaterialTheme.colorScheme.primary, onClick = { expanded = !expanded } ) { AnimatedContent( targetState = expanded, transitionSpec = { fadeIn(animationSpec = tween(150, 150)) with 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 } } } } ) { targetExpanded -> if (targetExpanded) { Expanded() } else { ContentIcon() } } }
Ein- und Ausblenden von Kindern animieren
Genau wie AnimatedVisibility
ist der Modifikator animateEnterExit
im Content-Lambda von AnimatedContent
verfügbar. Damit können Sie EnterAnimation
und ExitAnimation
auf jedes der direkten oder indirekten untergeordneten Elemente separat anwenden.
Benutzerdefinierte Animation hinzufügen
Genau wie bei AnimatedVisibility
ist das Feld transition
im Lambda von AnimatedContent
verfügbar. Hiermit 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 Überblendungsanimation. Durch Umstellung des an den Parameter current
übergebenen Werts wird der Inhalt mit einer Überblendungsanimation umgeschaltet.
var currentPage by remember { mutableStateOf("A") } Crossfade(targetState = currentPage) { screen -> when (screen) { "A" -> Text("Page A") "B" -> Text("Page B") } }
Integrierte Animationsmodifikatoren
Zusammensetzbare Größenänderungen mit animateContentSize
animieren
Der animateContentSize
-Modifikator animiert eine Größenänderung.
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 } ) { }
Animationen zu Listenelementen
Wenn Sie die Neuanordnung von Elementen in einer Lazy-Liste oder einem Lazy-Raster animieren möchten, sehen Sie sich die Dokumentation zur Animation von Lazy-Layoutelementen an.
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Wertbezogene Animationen
- Animationen in „Compose“
- Unterstützung für Animationstools {:#tooling}