Funkcja tworzenia ma wbudowane funkcje kompozycyjne i modyfikatory, które obsługują typowe przypadki użycia animacji.
Wbudowane animowane elementy kompozycyjne
Animacja wyglądu i zniknięcia za pomocą aplikacji AnimatedVisibility
Funkcja kompozycyjna AnimatedVisibility
animuje wygląd i znikanie swojej 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ę, zanikając i rozwijając, oraz znika w wyniku zanikania i zmniejszania. Przejście można dostosować, używając właściwości 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 powyższym przykładzie, możesz łączyć wiele obiektów EnterTransition
lub ExitTransition
za pomocą operatora +
, a każdy z nich akceptuje parametry opcjonalne, aby dostosować jego działanie. Więcej informacji znajdziesz w dokumentacji.
Przykłady: EnterTransition
i ExitTransition
AnimatedVisibility
zawiera też wariant, który wymaga parametru MutableTransitionState
. Dzięki temu możesz aktywować animację od razu po dodaniu obiektu 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" } ) }
Animuj wejście i wyjście dziecka
W przypadku elementów w obiekcie AnimatedVisibility
(bezpośrednie lub pośrednie elementy podrzędne) można użyć modyfikatora animateEnterExit
, aby określić różne zachowanie animacji przy poszczególnych elementach. Efekt wizualny w przypadku każdego z tych elementów podrzędnych to połączenie animacji określonych w komponencie AnimatedVisibility
oraz animacji wejścia i wyjścia dziecka.
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 zdecydować, że AnimatedVisibility
w ogóle nie będzie stosować animacji, żeby dzieci mogły mieć własne animacje za pomocą funkcji animateEnterExit
. Aby to zrobić, podaj EnterTransition.None
i ExitTransition.None
w komponencie AnimatedVisibility
.
Dodaj animację niestandardową
Jeśli chcesz dodać niestandardowe efekty animacji poza wbudowanymi animacjami wejścia i wyjścia, uzyskaj dostęp do bazowej instancji Transition
za pomocą właściwości transition
w obiekcie lambda treści dla AnimatedVisibility
. Wszystkie stany animacji dodane do instancji przejścia będą uruchamiane jednocześnie z animacjami wejścia i wyjścia w funkcji AnimatedVisibility
. AnimatedVisibility
czeka, aż wszystkie animacje w komponencie Transition
się zakończą, zanim usunie swoją zawartość.
W przypadku animacji wyjścia utworzonych niezależnie od parametru Transition
(np. z użyciem funkcji animate*AsState
) AnimatedVisibility
nie będzie w stanie ich uwzględnić, więc może usunąć kompozycję 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.
Animuj na podstawie stanu docelowego w AnimatedContent
Funkcja kompozycyjna AnimatedContent
animuje swoją zawartość, która zmienia się w zależności od stanu docelowego.
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") } }
Pamiętaj, że zawsze używaj parametru lambda i odzwierciedla go w treści. Interfejs API używa tej wartości jako klucza do identyfikowania treści, która jest wyświetlana w danej chwili.
Domyślnie początkowa treść zanika, a potem pojawia się treść docelowa (to zachowanie jest nazywane przenikaniem). Możesz dostosować działanie animacji, określając obiekt ContentTransform
w parametrze transitionSpec
. Możesz utworzyć ContentTransform
, łącząc EnterTransition
z ExitTransition
za pomocą funkcji with
infix. Możesz zastosować obiekt SizeTransform
do elementu ContentTransform
, dołączając go za pomocą funkcji infix za pomocą 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() 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") }
EnterTransition
określa, jak powinna wyglądać docelowa treść, a ExitTransition
określa, w jaki sposób powinna ona zniknąć. Oprócz wszystkich funkcji EnterTransition
i ExitTransition
dostępnych w AnimatedVisibility
AnimatedContent
oferuje też slideIntoContainer
i slideOutOfContainer
.
To wygodne alternatywy dla metod slideInHorizontally/Vertically
i slideOutHorizontally/Vertically
, które obliczają odległość slajdu na podstawie rozmiaru treści początkowej i docelowej treści AnimatedContent
.
SizeTransform
określa animację rozmiaru 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 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)) 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() } } }
Animuj przejście dziecka do wejścia i wyjścia
Tak jak w przypadku AnimatedVisibility
, modyfikator animateEnterExit
jest dostępny w lambda treści AnimatedContent
. Za jego pomocą możesz zastosować uprawnienia EnterAnimation
i ExitAnimation
do każdego bezpośredniego lub pośredniego elementu podrzędnego z osobna.
Dodaj animację niestandardową
Tak jak w polu AnimatedVisibility
, pole transition
jest dostępne w obrębie lambda treści AnimatedContent
. Użyj go, by utworzyć niestandardową animację, która będzie działać razem z przejściem AnimatedContent
. Szczegółowe informacje znajdziesz w sekcji updateMove.
Tworzenie animacji między 2 układami za pomocą funkcji Crossfade
Crossfade
przełącza się między 2 układami z użyciem przenikania. Po przełączeniu wartości przekazywanej do parametru current
treść jest przełączana z animacją przenikania.
var currentPage by remember { mutableStateOf("A") } Crossfade(targetState = currentPage) { screen -> when (screen) { "A" -> Text("Page A") "B" -> Text("Page B") } }
Wbudowane modyfikatory animacji
Animacja zmian rozmiaru kompozycyjnego za pomocą funkcji 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 w obrębie listy lub siatki leniwego, zapoznaj się z dokumentacją animacji elementów leniwego układu.
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony
- Animacje na podstawie wartości
- Animacje w sekcji Utwórz
- Obsługa narzędzi do animacji {:#tooling}