Compose zawiera wbudowane funkcje kompozycyjne i modyfikatory do obsługi typowych przypadków użycia animacji.
Wbudowane komponenty animowane
Animowanie pojawiania się i znikania za pomocą AnimatedVisibility

Kompozycja AnimatedVisibility
animuje pojawianie się i znikanie treści.
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 // ... }
Domyślnie treść pojawia się, gdy jest rozjaśniana i powiększana, a znika, gdy jest przyciemniana i pomniejszana. Przejście można dostosować, określając
EnterTransition
i
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) ) }
Jak widać w przykładzie powyżej, możesz łączyć wiele obiektów EnterTransition
lub ExitTransition
za pomocą operatora +
. Każdy z nich akceptuje opcjonalne parametry, które pozwalają dostosować jego działanie. Więcej informacji znajdziesz w sekcji Referencje.
Przykłady: EnterTransition
i ExitTransition
AnimatedVisibility
oferuje też wariant, który przyjmuje
MutableTransitionState
. Dzięki temu możesz uruchomić animację od razu po dodaniu elementu
AnimatedVisibility
do drzewa kompozycji. Przydaje się też do obserwowania stanu animacji.
// 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" } ) }
Animowanie wejść i wyjść dla dzieci
Treści w AnimatedVisibility
(bezpośrednie lub pośrednie elementy podrzędne) mogą używać modyfikatora
animateEnterExit
, aby określić różne zachowania animacji dla każdego z nich. Efekt wizualny każdego z tych elementów podrzędnych jest połączeniem animacji określonych w funkcji kompozycyjnej AnimatedVisibility
oraz animacji wejścia i wyjścia elementu podrzędnego.
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… } } }
W niektórych przypadkach możesz chcieć, aby atrybut AnimatedVisibility
nie stosował żadnych animacji, dzięki czemu każde dziecko będzie mogło mieć własne, odrębne animacje za pomocą atrybutu animateEnterExit
. Aby to osiągnąć, określ wartości EnterTransition.None
i ExitTransition.None
w funkcji AnimatedVisibility
.
Dodawanie animacji niestandardowej
Jeśli chcesz dodać niestandardowe efekty animacji wykraczające poza wbudowane animacje wejścia i wyjścia, uzyskaj dostęp do bazowej instancji Transition
za pomocą właściwości transition
w lambdzie treści dla AnimatedVisibility
. Wszystkie stany animacji dodane do instancji przejścia będą działać jednocześnie z animacjami wejścia i wyjścia elementu AnimatedVisibility
. AnimatedVisibility
czeka, aż wszystkie animacje w Transition
zostaną zakończone, zanim usunie jego zawartość.
W przypadku animacji wyjścia utworzonych niezależnie od Transition
(np. za pomocą animate*AsState
) AnimatedVisibility
nie będzie w stanie ich uwzględnić, dlatego może usunąć komponenty treści przed ich zakończeniem.
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) ) }
Szczegółowe informacje o Transition
znajdziesz w sekcji updateTransition.
Animowanie na podstawie stanu docelowego za pomocą AnimatedContent
Kompozycja AnimatedContent
animuje swoje treści, gdy zmieniają się one w zależności od stanu docelowego.
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") } }
Pamiętaj, że zawsze musisz używać parametru lambda i odzwierciedlać go w treści. Interfejs API używa tej wartości jako klucza do identyfikowania aktualnie wyświetlanych treści.
Domyślnie początkowa treść zanika, a potem pojawia się treść docelowa (takie zachowanie nazywa się przejściem przez zanikanie). Możesz dostosować to zachowanie animacji, określając obiekt ContentTransform
w parametrze transitionSpec
. Możesz utworzyć ContentTransform
, łącząc EnterTransition
z ExitTransition
za pomocą funkcji wrostkowej with
. Możesz zastosować SizeTransform
do ContentTransform
, dołączając go za pomocą funkcji wrostkowej 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
określa, jak powinny wyglądać treści docelowe, aExitTransition
określa, jak powinny znikać treści początkowe. Oprócz wszystkich funkcji EnterTransition
i ExitTransition
dostępnych w AnimatedVisibility
, AnimatedContent
oferuje slideIntoContainer
i slideOutOfContainer
.
Są to wygodne alternatywy dla slideInHorizontally/Vertically
i slideOutHorizontally/Vertically
, które obliczają odległość slajdu na podstawie rozmiarów treści początkowych i docelowych w AnimatedContent
.
SizeTransform
określa, jak rozmiar powinien się zmieniać między treściami początkowymi a docelowymi. Podczas tworzenia animacji masz dostęp zarówno do rozmiaru początkowego, jak i docelowego. SizeTransform
określa też, czy podczas animacji treść ma być przycinana do rozmiaru komponentu.
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() } } }
Animowanie przejść podczas wchodzenia i wychodzenia z podrzędnych elementów
Podobnie jak w przypadku AnimatedVisibility
, modyfikator animateEnterExit
jest dostępny w lambdzie treści AnimatedContent
. Użyj tego, aby zastosować EnterAnimation
i ExitAnimation
do każdego z bezpośrednich lub pośrednich elementów podrzędnych oddzielnie.
Dodawanie animacji niestandardowej
Podobnie jak AnimatedVisibility
, pole transition
jest dostępne w funkcji lambda treści AnimatedContent
. Użyj tej opcji, aby utworzyć niestandardowy efekt animacji, który będzie działać jednocześnie z AnimatedContent
przejściem. Szczegółowe informacje znajdziesz w sekcji updateTransition.
Animowanie przejścia między 2 układami za pomocą Crossfade
Crossfade
animuje przejście między dwoma układami za pomocą animacji przenikania. Przełączając wartość przekazywaną do parametru current
, możesz przełączać treści za pomocą animacji przenikania.
var currentPage by remember { mutableStateOf("A") } Crossfade(targetState = currentPage, label = "cross fade") { screen -> when (screen) { "A" -> Text("Page A") "B" -> Text("Page B") } }
Wbudowane modyfikatory animacji
Animowanie zmian rozmiaru komponentu za pomocą animateContentSize

Modyfikator animateContentSize
animuje zmianę rozmiaru.
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 } ) { }
Animacje elementów listy
Jeśli chcesz animować zmianę kolejności elementów na liście lub w siatce Lazy, zapoznaj się z dokumentacją animacji elementów układu Lazy.
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony.
- Animacje oparte na wartościach
- Animacje w Compose
- Obsługa narzędzi do animacji {:#tooling}