Compose include composabili e modificatori integrati per la gestione di casi d'uso comuni delle animazioni.
Elementi componibili animati integrati
Compose fornisce diversi componibili che animano la comparsa, la scomparsa e le modifiche del layout dei contenuti.
Anima la comparsa e la scomparsa
Il componibile AnimatedVisibility anima la comparsa e la scomparsa dei suoi contenuti.
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 // ... }
Per impostazione predefinita, i contenuti vengono visualizzati con una dissolvenza in entrata e un'espansione e scompaiono con una dissolvenza in uscita e una riduzione. Personalizza questa transizione specificando gli oggetti EnterTransition e ExitTransition.
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) ) }
Come mostrato nell'esempio precedente, puoi combinare più oggetti EnterTransition o ExitTransition con un operatore + e ognuno accetta parametri facoltativi per personalizzare il proprio comportamento. Per ulteriori informazioni, consulta le pagine di riferimento.
Esempi di transizioni di entrata e uscita
AnimatedVisibility offre anche una variante che accetta un argomento MutableTransitionState. In questo modo puoi attivare un'animazione non appena l'elemento componibile AnimatedVisibility viene aggiunto all'albero di composizione. È utile anche per osservare lo stato dell'animazione.
// 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" } ) }
Anima l'entrata e l'uscita per i bambini
I contenuti all'interno di AnimatedVisibility (elementi secondari diretti o indiretti) possono utilizzare il modificatore animateEnterExit per specificare un comportamento di animazione diverso per ciascuno di essi. L'effetto visivo per ciascuno di questi elementi secondari è una combinazione delle animazioni specificate nel composable AnimatedVisibility e delle animazioni di entrata e uscita dell'elemento secondario.
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 alcuni casi, potresti voler fare in modo che AnimatedVisibility non applichi alcuna animazione, in modo che i componenti secondari possano avere ciascuno le proprie animazioni distinte tramite animateEnterExit. Per farlo, specifica EnterTransition.None e ExitTransition.None nel componibile AnimatedVisibility.
Aggiungi animazione personalizzata
Se vuoi aggiungere effetti di animazione personalizzati oltre alle animazioni di entrata e uscita integrate, accedi all'istanza Transition sottostante utilizzando la proprietà transition all'interno della funzione lambda dei contenuti per AnimatedVisibility. Tutti gli stati di animazione aggiunti all'istanza Transition verranno eseguiti contemporaneamente alle animazioni di entrata e uscita di AnimatedVisibility. AnimatedVisibility attende che tutte le animazioni in Transition siano terminate prima di rimuovere i contenuti.
Per le animazioni di uscita create indipendentemente da Transition (ad esempio utilizzando animate*AsState), AnimatedVisibility non sarebbe in grado di tenerne conto e, di conseguenza, potrebbe rimuovere il composable dei contenuti prima che vengano completate.
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) ) }
Per scoprire di più sull'utilizzo di Transition per gestire le animazioni, consulta Anima più proprietà contemporaneamente con una transizione.
Animazione basata sullo stato di destinazione
Il componibile AnimatedContent anima i suoi contenuti man mano che cambiano in base a uno stato di destinazione.
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") } }
Per impostazione predefinita, i contenuti iniziali svaniscono e poi vengono visualizzati i contenuti di destinazione (questo comportamento è chiamato dissolvenza).
Puoi personalizzare questo comportamento dell'animazione specificando un oggetto ContentTransform per il parametro transitionSpec. Puoi creare un'istanza di ContentTransform combinando un oggetto EnterTransition con un oggetto ExitTransition utilizzando la funzione infissa with. Puoi applicare SizeTransform all'oggetto ContentTransform collegandolo alla funzione infissa using.
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") }

EnterTransition definisce l'aspetto dei contenuti di destinazione, mentre ExitTransition definisce la modalità di scomparsa dei contenuti iniziali. Oltre a tutte le funzioni EnterTransition e ExitTransition disponibili per AnimatedVisibility, AnimatedContent offre slideIntoContainer e slideOutOfContainer.
Si tratta di comode alternative a slideInHorizontally/Vertically e slideOutHorizontally/Vertically che calcolano la distanza di scorrimento in base alle dimensioni dei contenuti iniziali e dei contenuti di destinazione dei contenuti AnimatedContent.
SizeTransform definisce il modo in cui le dimensioni devono essere animate tra i contenuti iniziali e quelli di destinazione. Quando crei l'animazione, hai accesso sia alle dimensioni iniziali sia a quelle di destinazione. SizeTransform controlla anche se i contenuti devono essere ritagliati
in base alle dimensioni del componente durante le animazioni.
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() } } }

Anima le transizioni di entrata e uscita dei componenti secondari
Come AnimatedVisibility, il modificatore animateEnterExit è disponibile all'interno della funzione lambda dei contenuti di AnimatedContent. Utilizza questa opzione per applicare EnterAnimation e ExitAnimation a ciascuno degli elementi secondari diretti o indiretti separatamente.
Aggiungi animazione personalizzata
Come AnimatedVisibility, il campo transition è disponibile all'interno della lambda dei contenuti di AnimatedContent. Utilizzalo per creare un effetto di animazione personalizzato che viene eseguito contemporaneamente alla transizione AnimatedContent. Per i dettagli, consulta updateTransition.
Animazione tra due layout
Crossfade esegue l'animazione tra due layout con un'animazione di dissolvenza incrociata. Attivando/disattivando il valore passato al parametro current, i contenuti vengono cambiati con un'animazione con dissolvenza incrociata.
var currentPage by remember { mutableStateOf("A") } Crossfade(targetState = currentPage, label = "cross fade") { screen -> when (screen) { "A" -> Text("Page A") "B" -> Text("Page B") } }
Modificatori di animazione integrati
Compose fornisce modificatori per animare modifiche specifiche direttamente sui componibili.
Anima le modifiche alle dimensioni dei composabili
Il modificatore animateContentSize anima una modifica delle dimensioni.
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 } ) { }
Animazioni degli elementi dell'elenco
Se vuoi animare i riordinamenti degli elementi all'interno di un elenco o di una griglia Lazy, consulta la documentazione sull'animazione degli elementi del layout Lazy.
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Animazioni basate sul valore
- Animazioni in Compose
- Supporto degli strumenti di animazione {:#tooling}