Funkcja tworzenia wiadomości ma wiele wbudowanych mechanizmów animacji i może być przytłaczająca. musisz wybrać. Poniżej znajdziesz listę typowych zastosowań animacji. Dla: bardziej szczegółowe informacje na temat pełnego zestawu różnych dostępnych opcji interfejsu API. przeczytaj pełną dokumentację tworzenia animacji.
Animuj wspólne właściwości elementów kompozycyjnych
Compose zapewnia wygodne interfejsy API, które pozwalają rozwiązać wiele typowych problemów w przypadku animacji. W tej sekcji pokazujemy, jak animować typowe właściwości elementu kompozycyjnego.
Animacja pojawianie się / znikanie
![Zielony element kompozycyjny, który wyświetla się i ukrywa](https://developer.android.com/static/develop/ui/compose/images/animations/animated_visibility_column.gif?authuser=7&hl=pl)
Użyj AnimatedVisibility
, aby ukryć lub wyświetlić funkcję kompozycyjną. Dzieci w środku
AnimatedVisibility
może użyć karty Modifier.animateEnterExit()
do własnego zgłoszenia
lub wyjść z przejścia.
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 // ... }
Parametry wejścia i wyjścia parametru AnimatedVisibility
umożliwiają skonfigurowanie
funkcja kompozycyjna zachowuje się, gdy pojawia się i znika. Przeczytaj w całości
dokumentacji.
Inną opcją animowania widoczności funkcji kompozycyjnej jest
alfa na przestrzeni czasu za pomocą animateFloatAsState
:
var visible by remember { mutableStateOf(true) } val animatedAlpha by animateFloatAsState( targetValue = if (visible) 1.0f else 0f, label = "alpha" ) Box( modifier = Modifier .size(200.dp) .graphicsLayer { alpha = animatedAlpha } .clip(RoundedCornerShape(8.dp)) .background(colorGreen) .align(Alignment.TopCenter) ) { }
Jednak zmiana alfa wiąże się z zastrzeżeniem, że funkcja kompozycyjna pozostanie niezmieniona
w kompozycji i nadal zajmuje przestrzeń, Ten
może sprawić, że czytniki ekranu i inne mechanizmy ułatwień dostępu
elementu na ekranie. Z drugiej strony AnimatedVisibility
w końcu usuwa
obiektu z kompozycji.
![Animowanie wersji alfa funkcji kompozycyjnej](https://developer.android.com/static/develop/ui/compose/images/animations/animated_visibility_alpha.gif?authuser=7&hl=pl)
Animuj kolor tła
![Funkcja kompozycyjna, której kolor tła zmienia się z czasem jako animacja, w której kolory przechodzą na siebie.](https://developer.android.com/static/develop/ui/compose/images/animations/animated_forever.gif?authuser=7&hl=pl)
val animatedColor by animateColorAsState( if (animateBackgroundColor) colorGreen else colorBlue, label = "color" ) Column( modifier = Modifier.drawBehind { drawRect(animatedColor) } ) { // your composable here }
Ta opcja jest skuteczniejsza niż Modifier.background()
.
Dla jednego ustawienia koloru można zastosować Modifier.background()
, ale gdy
animowanie koloru w czasie, może spowodować większą liczbę zmian kompozycji niż
niezbędną.
Nieskończoną animację koloru tła znajdziesz w sekcji powtarzanie animacji .
Animuj rozmiar elementu kompozycyjnego
![Rozmiar zielonego elementu kompozycyjnego zmienia się płynnie.](https://developer.android.com/static/develop/ui/compose/images/animations/animated_content_size.gif?authuser=7&hl=pl)
Funkcja tworzenia umożliwia animowanie rozmiaru elementów kompozycyjnych na kilka różnych sposobów. Używaj
animateContentSize()
– animacje między zmianami rozmiaru kompozycyjnego.
Jeśli na przykład masz pole zawierające tekst, które można rozwinąć od 1 do
Możesz użyć wielu linii Modifier.animateContentSize()
, aby zwiększyć płynność
przejście:
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 } ) { }
Możesz też użyć atrybutu AnimatedContent
z SizeTransform
, aby opisać
jak powinny
wprowadzać się zmiany rozmiaru.
Animuj położenie funkcji kompozycyjnej
![Funkcja kompozycyjna w kolorze zielonym płynnie animowana w dół i w prawo](https://developer.android.com/static/develop/ui/compose/images/animations/animated_offset.gif?authuser=7&hl=pl)
Aby animować położenie funkcji kompozycyjnej, użyj operatora Modifier.offset{ }
w połączeniu z
animateIntOffsetAsState()
var moved by remember { mutableStateOf(false) } val pxToMove = with(LocalDensity.current) { 100.dp.toPx().roundToInt() } val offset by animateIntOffsetAsState( targetValue = if (moved) { IntOffset(pxToMove, pxToMove) } else { IntOffset.Zero }, label = "offset" ) Box( modifier = Modifier .offset { offset } .background(colorBlue) .size(100.dp) .clickable( interactionSource = remember { MutableInteractionSource() }, indication = null ) { moved = !moved } )
Aby elementy kompozycyjne nie były rysowane nad ani pod innymi
elementów kompozycyjnych podczas animowania pozycji lub rozmiaru, użyj funkcji Modifier.layout{ }
. Ten
powoduje przekazywanie zmian rozmiaru i pozycji do elementu nadrzędnego, co wpływa na
innych dzieci.
Na przykład jeśli przenosisz element Box
w elemencie Column
i innych elementach podrzędnych
które musisz przesunąć, gdy przesuwa się Box
, uwzględnij informacje o przesunięciu
Modifier.layout{ }
w następujący sposób:
var toggled by remember { mutableStateOf(false) } val interactionSource = remember { MutableInteractionSource() } Column( modifier = Modifier .padding(16.dp) .fillMaxSize() .clickable(indication = null, interactionSource = interactionSource) { toggled = !toggled } ) { val offsetTarget = if (toggled) { IntOffset(150, 150) } else { IntOffset.Zero } val offset = animateIntOffsetAsState( targetValue = offsetTarget, label = "offset" ) Box( modifier = Modifier .size(100.dp) .background(colorBlue) ) Box( modifier = Modifier .layout { measurable, constraints -> val offsetValue = if (isLookingAhead) offsetTarget else offset.value val placeable = measurable.measure(constraints) layout(placeable.width + offsetValue.x, placeable.height + offsetValue.y) { placeable.placeRelative(offsetValue) } } .size(100.dp) .background(colorGreen) ) Box( modifier = Modifier .size(100.dp) .background(colorBlue) ) }
![2 pola, w których druga ramka animuje swoje położenie X i Y, a trzecia odpowiada, poruszając się również o Y.](https://developer.android.com/static/develop/ui/compose/images/animations/animated_layout_modifier.gif?authuser=7&hl=pl)
Modifier.layout{ }
Animowane dopełnienie elementu kompozycyjnego
![Zielona funkcja kompozycyjna staje się coraz mniejsza z każdym kliknięciem, z animowanym dopełnieniem](https://developer.android.com/static/develop/ui/compose/images/animations/animated_padding.gif?authuser=7&hl=pl)
Aby animować dopełnienie funkcji kompozycyjnej, użyj właściwości animateDpAsState
w połączeniu z
Modifier.padding()
:
var toggled by remember { mutableStateOf(false) } val animatedPadding by animateDpAsState( if (toggled) { 0.dp } else { 20.dp }, label = "padding" ) Box( modifier = Modifier .aspectRatio(1f) .fillMaxSize() .padding(animatedPadding) .background(Color(0xff53D9A1)) .clickable( interactionSource = remember { MutableInteractionSource() }, indication = null ) { toggled = !toggled } )
Animuj wysokość elementu kompozycyjnego
Aby animować wysokość elementu kompozycyjnego, użyj funkcji animateDpAsState
w połączeniu z
Modifier.graphicsLayer{ }
W przypadku jednorazowej zmiany wysokości użyj funkcji
Modifier.shadow()
Jeśli animujesz cień, za pomocą funkcji
Modyfikator Modifier.graphicsLayer{ }
jest skuteczniejszą opcją.
val mutableInteractionSource = remember { MutableInteractionSource() } val pressed = mutableInteractionSource.collectIsPressedAsState() val elevation = animateDpAsState( targetValue = if (pressed.value) { 32.dp } else { 8.dp }, label = "elevation" ) Box( modifier = Modifier .size(100.dp) .align(Alignment.Center) .graphicsLayer { this.shadowElevation = elevation.value.toPx() } .clickable(interactionSource = mutableInteractionSource, indication = null) { } .background(colorGreen) ) { }
Możesz też użyć funkcji kompozycyjnej Card
i ustawić właściwość wysokości nad poziomem morza na
różne wartości dla każdego stanu.
Animuj skalę, przesunięcie i obrót tekstu
![Tekst do kompozycji mówi](https://developer.android.com/static/develop/ui/compose/images/animations/animated_text.gif?authuser=7&hl=pl)
Podczas animowania skali, przesunięcia lub obrotu tekstu ustaw textMotion
od TextStyle
do TextMotion.Animated
. Zapewnia to płynniejsze działanie
przejścia między animacjami tekstowymi. Użyj aplikacji Modifier.graphicsLayer{ }
, aby:
przetłumaczyć, obrócić ani przeskalować tekst.
val infiniteTransition = rememberInfiniteTransition(label = "infinite transition") val scale by infiniteTransition.animateFloat( initialValue = 1f, targetValue = 8f, animationSpec = infiniteRepeatable(tween(1000), RepeatMode.Reverse), label = "scale" ) Box(modifier = Modifier.fillMaxSize()) { Text( text = "Hello", modifier = Modifier .graphicsLayer { scaleX = scale scaleY = scale transformOrigin = TransformOrigin.Center } .align(Alignment.Center), // Text composable does not take TextMotion as a parameter. // Provide it via style argument but make sure that we are copying from current theme style = LocalTextStyle.current.copy(textMotion = TextMotion.Animated) ) }
Animuj kolor tekstu
![Słowa](https://developer.android.com/static/develop/ui/compose/images/animations/animated_text_color.gif?authuser=7&hl=pl)
Aby animować kolor tekstu, użyj funkcji lambda color
w komponencie kompozycyjnym BasicText
:
val infiniteTransition = rememberInfiniteTransition(label = "infinite transition") val animatedColor by infiniteTransition.animateColor( initialValue = Color(0xFF60DDAD), targetValue = Color(0xFF4285F4), animationSpec = infiniteRepeatable(tween(1000), RepeatMode.Reverse), label = "color" ) BasicText( text = "Hello Compose", color = { animatedColor }, // ... )
Przełączanie się między różnymi typami treści
![Zielony ekran mówi](https://developer.android.com/static/develop/ui/compose/images/animations/animated_content_slower.gif?authuser=7&hl=pl)
Użyj AnimatedContent
, aby przełączać się między różnymi elementami kompozycyjnymi, jeśli:
aby standardowe rozjaśnianie elementów kompozycyjnych, użyj Crossfade
.
var state by remember { mutableStateOf(UiState.Loading) } AnimatedContent( state, transitionSpec = { fadeIn( animationSpec = tween(3000) ) togetherWith fadeOut(animationSpec = tween(3000)) }, modifier = Modifier.clickable( interactionSource = remember { MutableInteractionSource() }, indication = null ) { state = when (state) { UiState.Loading -> UiState.Loaded UiState.Loaded -> UiState.Error UiState.Error -> UiState.Loading } }, label = "Animated Content" ) { targetState -> when (targetState) { UiState.Loading -> { LoadingScreen() } UiState.Loaded -> { LoadedScreen() } UiState.Error -> { ErrorScreen() } } }
AnimatedContent
można dostosować, tak aby wyświetlać wiele różnych rodzajów wiadomości
przejściach typu wyjściowego. Więcej informacji znajdziesz w dokumentacji
AnimatedContent
lub przeczytaj tego posta na blogu
AnimatedContent
Animuj podczas nawigacji do różnych miejsc
![2 kompozycje, jeden zielony z napisem „Lądowanie”, a drugi niebieski z nazwą „Szczegóły” animowany przez przesuwanie kompozycyjnego detalu po stronie docelowej.](https://developer.android.com/static/develop/ui/compose/images/animations/navigation_compose_animation.gif?authuser=7&hl=pl)
Aby animować przejścia między elementami kompozycyjnymi, gdy używany jest
artefakt nawigowanie-compose, określ parametry enterTransition
oraz
exitTransition
w funkcji kompozycyjnej. Możesz też ustawić animację domyślną
używany w przypadku wszystkich miejsc docelowych na najwyższym poziomie (NavHost
):
val navController = rememberNavController() NavHost( navController = navController, startDestination = "landing", enterTransition = { EnterTransition.None }, exitTransition = { ExitTransition.None } ) { composable("landing") { ScreenLanding( // ... ) } composable( "detail/{photoUrl}", arguments = listOf(navArgument("photoUrl") { type = NavType.StringType }), enterTransition = { fadeIn( animationSpec = tween( 300, easing = LinearEasing ) ) + slideIntoContainer( animationSpec = tween(300, easing = EaseIn), towards = AnimatedContentTransitionScope.SlideDirection.Start ) }, exitTransition = { fadeOut( animationSpec = tween( 300, easing = LinearEasing ) ) + slideOutOfContainer( animationSpec = tween(300, easing = EaseOut), towards = AnimatedContentTransitionScope.SlideDirection.End ) } ) { backStackEntry -> ScreenDetails( // ... ) } }
Istnieje wiele różnych rodzajów przejść, w zależności od charakteru treści przychodzących i wychodzących, zapoznaj się z dokumentacja.
Powtarzanie animacji
![Zielone tło, które w nieskończoność przekształca się w niebieskie tło, które wyświetla się w wybranym kolorze.](https://developer.android.com/static/develop/ui/compose/images/animations/animated_forever.gif?authuser=7&hl=pl)
Użyj domeny rememberInfiniteTransition
w połączeniu z: infiniteRepeatable
animationSpec
, aby powtarzać animację w sposób ciągły. Zmień RepeatModes
na
i określić, jak ma się to odbywać.
Użyj funkcji finiteRepeatable
, aby powtórzyć określoną liczbę razy.
val infiniteTransition = rememberInfiniteTransition(label = "infinite") val color by infiniteTransition.animateColor( initialValue = Color.Green, targetValue = Color.Blue, animationSpec = infiniteRepeatable( animation = tween(1000, easing = LinearEasing), repeatMode = RepeatMode.Reverse ), label = "color" ) Column( modifier = Modifier.drawBehind { drawRect(color) } ) { // your composable here }
Włącz animację przy uruchomieniu funkcji kompozycyjnej
Narzędzie LaunchedEffect
jest uruchamiane, gdy do kompozycji pojawi się funkcja kompozycyjna. Zaczyna się
możesz utworzyć animację przy uruchomieniu funkcji kompozycyjnej,
zmiany stanu. Użycie Animatable
z metodą animateTo
do uruchamiania
animacja przy uruchomieniu:
val alphaAnimation = remember { Animatable(0f) } LaunchedEffect(Unit) { alphaAnimation.animateTo(1f) } Box( modifier = Modifier.graphicsLayer { alpha = alphaAnimation.value } )
Twórz sekwencyjne animacje
![Cztery okręgi z animowanymi zielonymi strzałkami między nimi, animowanymi po kolei.](https://developer.android.com/static/develop/ui/compose/images/animations/multiple_properties_sequential.gif?authuser=7&hl=pl)
Używaj wewnętrznych interfejsów API Animatable
do wykonywania sekwencyjnych lub równoczesnych
ani animacji. Wywołuję animateTo
(Animatable
) jeden po drugim
Kolejne animacje będą czekać na zakończenie poprzednich animacji .
Dzieje się tak, ponieważ jest to funkcja zawieszenia.
val alphaAnimation = remember { Animatable(0f) } val yAnimation = remember { Animatable(0f) } LaunchedEffect("animationKey") { alphaAnimation.animateTo(1f) yAnimation.animateTo(100f) yAnimation.animateTo(500f, animationSpec = tween(100)) }
Tworzenie równoczesnych animacji
![Trzy animowane okręgi z zielonymi strzałkami, które są połączone w tym samym czasie.](https://developer.android.com/static/develop/ui/compose/images/animations/multiple_properties.gif?authuser=7&hl=pl)
użyj wewnętrznych interfejsów API (Animatable#animateTo()
lub animate
);
interfejs API Transition
do tworzenia równoczesnych animacji. Jeśli używasz wielu funkcji
gdy funkcje są uruchamiane w kontekście, uruchamiają animacje w tym samym
godzina:
val alphaAnimation = remember { Animatable(0f) } val yAnimation = remember { Animatable(0f) } LaunchedEffect("animationKey") { launch { alphaAnimation.animateTo(1f) } launch { yAnimation.animateTo(100f) } }
Można użyć interfejsu API updateTransition
, aby użyć tego samego stanu do kierowania
możesz korzystać z wielu różnych animacji. Animowany przykład poniżej
2 właściwości kontrolowane przez zmianę stanu: rect
i borderWidth
:
var currentState by remember { mutableStateOf(BoxState.Collapsed) } val transition = updateTransition(currentState, label = "transition") val rect by transition.animateRect(label = "rect") { state -> when (state) { BoxState.Collapsed -> Rect(0f, 0f, 100f, 100f) BoxState.Expanded -> Rect(100f, 100f, 300f, 300f) } } val borderWidth by transition.animateDp(label = "borderWidth") { state -> when (state) { BoxState.Collapsed -> 1.dp BoxState.Expanded -> 0.dp } }
Optymalizacja wydajności animacji
Animacje w Compose mogą powodować problemy z wydajnością. Wynika to z natury animacji: szybkie przesuwanie lub zmienianie pikseli na ekranie. klatka po klatce, aby stworzyć iluzję ruchu.
Weź pod uwagę różne fazy tworzenia wiadomości: kompozycję, układ i rysowanie. Jeśli animacja zmienia fazę układu, przez co wszystkie elementy kompozycyjne, których dotyczy problem, muszą i przekazywać nowe informacje. Jeśli animacja ma miejsce w fazie rysowania, być domyślnie wydajniejsze niż w przypadku uruchamiania animacji w układzie ponieważ wykonanoby mniej pracy.
Aby mieć pewność, że podczas tworzenia animacji aplikacja będzie robić jak najwięcej, wybierz lambda
wersji Modifier
tam, gdzie to możliwe. Pomija to zmianę kompozycji i działa
animacji poza fazą kompozycji, w przeciwnym razie użyj funkcji
Modifier.graphicsLayer{ }
, ponieważ ten modyfikator zawsze działa podczas rysowania
te etapy. Więcej informacji na ten temat znajdziesz w sekcji o odwracaniu odczytów w artykule
zapoznaj się z dokumentacją wyników.
Zmiana czasu animacji
Domyślnie w tworzeniu większości animacji używane są animacje wiosenne. Springs,
oparte na fizyce, są bardziej naturalne. Są też przerywane,
biorą one pod uwagę aktualną prędkość obiektu, a nie stały czas.
Jeśli chcesz zastąpić ustawienia domyślne, użyj wszystkich interfejsów API animacji pokazanych powyżej
możesz ustawić animationSpec
, aby dostosować sposób działania animacji,
czy wolisz, aby wykonywały się przez określony czas, czy były bardziej dynamiczne.
Oto podsumowanie różnych opcji animationSpec
:
spring
: animacja oparta na fizyce, domyślna dla wszystkich animacji. Ty można zmienić sztywność lub współczynnik tłumienia, aby uzyskać inną animację wygląd i styl.tween
(skrót od Between): animacja zależna od czasu trwania, animacja między 2 wartościami za pomocą funkcjiEasing
.keyframes
: specyfikacja określania wartości w konkretnych kluczowych punktach animację.repeatable
: specyfikacja oparta na czasie trwania, która działa określoną liczbę razy. określone przezRepeatMode
.infiniteRepeatable
: specyfikacja oparta na czasie trwania, która działa bezterminowo.snap
: automatycznie przyciąga reklamę do wartości końcowej bez żadnej animacji.
![Wpisz tutaj swój tekst alternatywny](https://developer.android.com/static/develop/ui/compose/images/animations/animated_spec_set.gif?authuser=7&hl=pl)
Przeczytaj pełną dokumentację, aby dowiedzieć się więcej na temat parametru animationSpecs.
Dodatkowe materiały
Więcej przykładów zabawnych animacji w funkcji tworzenia wiadomości znajdziesz na tych stronach:
- 5 szybkich animacji w funkcji Utwórz
- Poruszanie się wśród meduzy
- Dostosowywanie elementu
AnimatedContent
w funkcji Compose - Wygładzanie funkcji wygładzania w narzędziu Compose