Podstawy animate*AsState
Płynnie animuj pojedyncze wartości
Podstawy animate*AsState to bezpłatna lekcja Android Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Android Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Android Academy zawiera 4 lekcji w sumie.
Animowanie pojedynczej wartości
Najprostszym sposobem animowania w Compose jest rodzina animate*AsState. Przekazuje mu Pan/Pani wartość docelową, a w wyniku otrzymuje State, który płynnie animuje się od bieżącej wartości do wartości docelowej za każdym razem, gdy cel się zmieni.
Dla każdego typowego typu istnieje odpowiedni wariant: animateFloatAsState, animateDpAsState, animateColorAsState, animateOffsetAsState i inne.
animateFloatAsState
animateFloatAsState animuje pojedynczą wartość Float. Częstym zastosowaniem jest przezroczystość (alpha). Gdy wartość visible się zmieni, zwracana wartość alpha płynnie przechodzi między 0f a 1f.
Proszę zwrócić uwagę na słowo kluczowe by: pozwala ono odczytywać animowany State<Float> bezpośrednio jako zwykły Float.
@Composable
fun FadingLabel(visible: Boolean) {
val alpha by animateFloatAsState(
targetValue = if (visible) 1f else 0f,
label = "alpha"
)
Text(
"Hello",
modifier = Modifier.graphicsLayer { this.alpha = alpha }
)
}animateDpAsState
Rozmiary i przesunięcia interfejsu użytkownika korzystają z Dp, dlatego do animowania wypełnienia, rozmiaru lub pozycji warto użyć animateDpAsState.
W tym przykładzie pole po przełączeniu rośnie z 80dp do 160dp. Ponieważ animowany element Dp przekazujemy do size(), pole płynnie zmienia rozmiar.
@Composable
fun GrowingBox(big: Boolean) {
val size by animateDpAsState(
targetValue = if (big) 160.dp else 80.dp,
label = "size"
)
Box(
Modifier
.size(size)
.background(Color.Blue)
)
}animateColorAsState
Do animowania kolorów służy animateColorAsState. Interpoluje on w przestrzeni kolorów, dzięki czemu przejścia wyglądają płynnie i naturalnie, zamiast migotać przez nietypowe odcienie pośrednie.
W tym przykładzie kropka stanu animuje się między czerwonym a zielonym kolorem na podstawie wartości logicznej.
@Composable
fun StatusDot(online: Boolean) {
val color by animateColorAsState(
targetValue = if (online) Color(0xFF4CAF50) else Color(0xFFF44336),
label = "status-color"
)
Box(
Modifier
.size(16.dp)
.clip(CircleShape)
.background(color)
)
}Dostosowywanie za pomocą animationSpec
Domyślnie te funkcje pomocnicze korzystają z łagodnej sprężyny. Przekazanie animationSpec pozwala kontrolować czas trwania. Do ustalonego czasu trwania z krzywą easing należy użyć tween.
Ten panel przesuwa się przez 400 ms po płynnej krzywej, która najpierw przyspiesza, a następnie zwalnia.
@Composable
fun SlidingPanel(open: Boolean) {
val offset by animateDpAsState(
targetValue = if (open) 0.dp else 250.dp,
animationSpec = tween(
durationMillis = 400,
easing = FastOutSlowInEasing
),
label = "offset"
)
Box(Modifier.offset(x = offset)) { /* content */ }
}Krzywe easing
Easing określa sposób przyspieszania i zwalniania animacji. Compose udostępnia kilka krzywych:
LinearEasing— stała prędkość (mechaniczne wrażenie).FastOutSlowInEasing— domyślna krzywa Material; szybki początek i łagodne zakończenie.LinearOutSlowInEasing— dla elementów pojawiających się na ekranie.FastOutLinearInEasing— dla elementów opuszczających ekran.
Wybór właściwego easing sprawia, że ruch wydaje się zamierzony, a nie zrobotyzowany.
val progress by animateFloatAsState(
targetValue = if (done) 1f else 0f,
animationSpec = tween(500, easing = LinearOutSlowInEasing),
label = "progress"
)Specyfikacje sprężyn
Zamiast ustalonego czasu trwania można użyć sprężyny, która daje fizyczne i naturalne wrażenie. Sprężynę definiują dampingRatio (określający sprężystość) i stiffness (określający szybkość).
Sprężyny są świetnym rozwiązaniem, ponieważ płynnie dostosowują się nawet wtedy, gdy cel zmieni się w trakcie animacji.
val scale by animateFloatAsState(
targetValue = if (active) 1.2f else 1f,
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessLow
),
label = "scale"
)Reagowanie na zakończenie
Czasami trzeba wykonać działanie po zakończeniu animacji, na przykład wywołać callback, gdy wartość osiągnie cel. animate*AsState udostępnia do tego celu parametr finishedListener.
val alpha by animateFloatAsState(
targetValue = if (gone) 0f else 1f,
label = "alpha",
finishedListener = { finalValue ->
if (finalValue == 0f) onFullyHidden()
}
)Animowanie wielu właściwości
Można połączyć kilka wywołań animate*AsState, aby jednocześnie animować więcej niż jedną właściwość. Każde z nich śledzi własną wartość, a razem tworzą bogatszy efekt.
W tym przykładzie element chip skaluje się i zmienia kolor po zaznaczeniu.
@Composable
fun SelectableChip(selected: Boolean, text: String) {
val scale by animateFloatAsState(if (selected) 1.1f else 1f, label = "s")
val bg by animateColorAsState(
if (selected) Color(0xFF3F51B5) else Color.LightGray,
label = "bg"
)
Box(
Modifier
.graphicsLayer { scaleX = scale; scaleY = scale }
.clip(RoundedCornerShape(16.dp))
.background(bg)
.padding(horizontal = 12.dp, vertical = 6.dp)
) { Text(text) }
}Sprężyna w czystym Kotlinie
Aby wyrobić sobie intuicję dotyczącą działania sprężyny, przedstawiamy krótką symulację w czystym Kotlinie. W każdym kroku delikatnie przesuwa ona wartość w kierunku celu, stosując pewne tłumienie — podobnie jak sprężyna Compose dąży do wartości docelowej przez wiele klatek.
fun main() {
var value = 0f
val target = 100f
var velocity = 0f
val stiffness = 0.1f
val damping = 0.6f
repeat(6) { step ->
val force = (target - value) * stiffness
velocity = (velocity + force) * damping
value += velocity
println("step $step -> ${"%.1f".format(value)}")
}
}Animowanie Int i Offset
Ta rodzina wykracza poza liczby zmiennoprzecinkowe i kolory. animateIntAsState służy do wartości całkowitych, takich jak docelowa liczba na plakietce, a animateOffsetAsState lub animateIntOffsetAsState pozwala animować pozycję 2D w jednym wywołaniu.
W tym przykładzie element chip przesuwa się po przekątnej dzięki animowaniu IntOffset.
@Composable
fun SlidingChip(moved: Boolean) {
val pos by animateIntOffsetAsState(
targetValue = if (moved) IntOffset(120, 60) else IntOffset.Zero,
label = "pos"
)
Box(
Modifier
.offset { pos }
.size(40.dp)
.background(Color.Magenta)
)
}Szybkie sprawdzenie
Chce Pan/Pani płynnie animować szerokość pola, mierzoną w Dp, gdy zmienia się wartość logiczna. Który interfejs API będzie najlepszy?
Podsumowanie: animate*AsState
Rodzina animate*AsState jest podstawowym rozwiązaniem do animowania pojedynczej wartości:
- Należy wybrać wariant odpowiedni dla typu:
animateFloatAsState,animateDpAsState,animateColorAsStateitd. - Należy ustawić
targetValue; wynik animuje się w jego kierunku przy każdej zmianie. - Ruchem można sterować za pomocą
animationSpec, używająctweenz easingiem lubspring. - Kilka funkcji można połączyć, aby animować wiele właściwości jednocześnie.
- Parametr
finishedListenerpozwala reagować na zakończenie animacji.
Następnie: animowanie pojawiania się i znikania treści za pomocą AnimatedVisibility i przejść.
Często zadawane pytania
Czy lekcja „Podstawy animate*AsState” jest bezpłatna?
Tak — pełny tekst „Podstawy animate*AsState” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Android Academy, przejdź na CoddyKit PRO. Kurs Android Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Podstawy animate*AsState”?
Płynnie animuj pojedyncze wartości Ćwiczysz Android Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Android Academy?
Nie wymagamy żadnego doświadczenia. Android Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Podstawy animate*AsState”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Android Academy?
Tak. Każda lekcja Android Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Dlaczego animacje mają znaczenie
- Podstawy animate*AsState
- AnimatedVisibility i przejścia
- Animacje gestów i sprężynowe