Compose zawiera wbudowane funkcje kompozycyjne i modyfikatory do obsługi typowych przypadków użycia animacji.
Wbudowane animowane funkcje kompozycyjne
Compose udostępnia kilka funkcji kompozycyjnych, które animują pojawianie się i znikanie treści oraz zmiany układu.
Animowanie pojawiania się i znikania
Funkcja kompozycyjna
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ę przez stopniowe rozjaśnianie i powiększanie, a znika przez stopniowe przyciemnianie i zmniejszanie. Możesz dostosować to przejście, określając
EnterTransition i ExitTransition obiekty.
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 pokazano w poprzednim przykładzie, możesz łączyć ze sobą 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 na stronach referencyjnych.
Przykłady przejść przy pojawianiu się i znikaniu
AnimatedVisibility oferuje też wariant, który przyjmuje argument MutableTransitionState. Dzięki temu możesz uruchomić animację, gdy tylko funkcja kompozycyjna AnimatedVisibility zostanie dodana do drzewa kompozycji. Jest to też przydatne 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 pojawiania się i znikania elementów podrzędnych
Treści w AnimatedVisibility (bezpośrednie lub pośrednie elementy podrzędne) mogą używać
animateEnterExit
modyfikatora, aby określić różne zachowania animacji dla każdego z nich. Efekt wizualny dla każdego z tych elementów podrzędnych jest połączeniem animacji określonych w funkcji kompozycyjnej AnimatedVisibility oraz własnych animacji pojawiania się i znikania 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 AnimatedVisibility nie stosowała żadnych animacji, tak aby elementy podrzędne mogły mieć własne, odrębne animacje za pomocą animateEnterExit. Aby to osiągnąć, określ EnterTransition.None i ExitTransition.None w funkcji kompozycyjnej AnimatedVisibility.
Dodawanie animacji niestandardowej
Jeśli chcesz dodać niestandardowe efekty animacji wykraczające poza wbudowane animacje pojawiania się i znikania, 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 Transition będą działać jednocześnie z animacjami pojawiania się i znikania AnimatedVisibility. AnimatedVisibility czeka, aż wszystkie animacje w Transition się zakończą, zanim usunie swoją treść.
W przypadku animacji znikania utworzonych niezależnie od Transition (np. za pomocą animate*AsState) AnimatedVisibility nie będzie w stanie ich uwzględnić i dlatego może usunąć funkcję kompozycyjną treści, zanim się zakończą.
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) ) }
Więcej informacji o używaniu Transition do zarządzania animacjami znajdziesz w artykule Animowanie
wielu właściwości jednocześnie za pomocą przejścia.
Animowanie na podstawie stanu docelowego
Funkcja kompozycyjna AnimatedContent
animuje swoją treść, gdy zmienia się ona na podstawie 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") } }
Domyślnie początkowa treść stopniowo znika, a potem stopniowo pojawia się treść docelowa
(to zachowanie nazywa się
przejściem).
Możesz dostosować to zachowanie animacji, określając a
ContentTransform
obiekt w parametrze transitionSpec. Możesz utworzyć instancję ContentTransform przez połączenie obiektu EnterTransition z obiektem ExitTransition za pomocą funkcji wrostkowej with. Możesz zastosować SizeTransform
do obiektu 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 ma się pojawiać treść docelowa, a ExitTransition – jak ma znikać treść początkowa. Oprócz
wszystkich funkcji EnterTransition i ExitTransition dostępnych dla
AnimatedVisibility, AnimatedContent oferuje slideIntoContainer
i slideOutOfContainer.
Są to wygodne alternatywy dla slideInHorizontally/Vertically i slideOutHorizontally/Vertically, które obliczają odległość przesunięcia na podstawie rozmiarów treści początkowej i docelowej funkcji kompozycyjnej AnimatedContent.
SizeTransform określa, jak rozmiar ma się animować między treścią początkową a docelową. Podczas tworzenia animacji masz dostęp zarówno do rozmiaru początkowego, jak i docelowego. SizeTransform określa też, czy treść ma być przycinana do rozmiaru komponentu podczas animacji.
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ść przy pojawianiu się i znikaniu elementów podrzędnych
Podobnie jak w przypadku AnimatedVisibility, modyfikator animateEnterExit
jest dostępny w lambdzie treści AnimatedContent. Użyj go, aby zastosować EnterAnimation i ExitAnimation do każdego z bezpośrednich lub pośrednich elementów podrzędnych osobno.
Dodawanie animacji niestandardowej
Podobnie jak w przypadku AnimatedVisibility, pole transition jest dostępne w lambdzie treści AnimatedContent. Użyj go, aby utworzyć niestandardowy efekt animacji, który będzie działać jednocześnie z przejściem AnimatedContent. Szczegóły znajdziesz w artykule
updateTransition.
Animowanie między 2 układami
Crossfade animuje przejście między 2 układami za pomocą animacji przenikania. Przełączając wartość przekazywaną do parametru current, treść jest przełączana 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
Compose udostępnia modyfikatory do animowania konkretnych zmian bezpośrednio w funkcjach kompozycyjnych.
Animowanie zmian rozmiaru funkcji kompozycyjnej
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 język JavaScript jest wyłączony.
- Animacje na podstawie wartości
- Animacje w Compose
- Obsługa narzędzi do animacji {:#tooling}