Wiele interfejsów API animacji zwykle akceptuje parametry umożliwiające dostosowanie ich działania.
Dostosowywanie animacji za pomocą parametru AnimationSpec
Większość interfejsów API animacji umożliwia programistom dostosowywanie specyfikacji animacji za pomocą opcjonalnego parametru AnimationSpec
.
val alpha: Float by animateFloatAsState( targetValue = if (enabled) 1f else 0.5f, // Configure the animation duration and easing. animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing), label = "alpha" )
Istnieją różne rodzaje AnimationSpec
, które umożliwiają tworzenie różnych typów animacji.
Tworzenie animacji opartych na fizyce za pomocą spring
spring
tworzy animację opartą na fizyce między wartościami początkowymi i końcowymi. Przyjmuje 2 parametry: dampingRatio
i stiffness
.
dampingRatio
określa, jak sprężysta powinna być sprężyna. Wartością domyślną jest Spring.DampingRatioNoBouncy
.
stiffness
określa, jak szybko sprężyna powinna przesuwać się w kierunku wartości końcowej. Wartością domyślną jest Spring.StiffnessMedium
.
val value by animateFloatAsState( targetValue = 1f, animationSpec = spring( dampingRatio = Spring.DampingRatioHighBouncy, stiffness = Spring.StiffnessMedium ), label = "spring spec" )
spring
lepiej radzi sobie z przerwami niż typy oparte na czasie trwania,AnimationSpec
ponieważ gwarantuje ciągłość prędkości, gdy wartość docelowa zmienia się w trakcie animacji. spring
jest używany jako domyślny element AnimationSpec przez wiele interfejsów API animacji, takich jak animate*AsState
i updateTransition
.
Jeśli na przykład zastosujemy konfigurację spring
do poniższej animacji, która jest wywoływana przez dotyk użytkownika, to po przerwaniu animacji w trakcie jej trwania widać, że użycie tween
nie reaguje tak płynnie jak użycie spring
.
tween
i spring
dla animacji oraz przerywanie jej.Animacja między wartościami początkową i końcową z krzywą łagodzenia o wartości tween
tween
animuje wartości od początkowej do końcowej w określonym czasiedurationMillis
, używając krzywej wygładzania. tween
to skrót od słowa „between” (między), ponieważ funkcja ta sprawdza, czy wartość znajduje się między dwiema innymi wartościami.
Możesz też użyć wartości delayMillis
, aby opóźnić rozpoczęcie animacji.
val value by animateFloatAsState( targetValue = 1f, animationSpec = tween( durationMillis = 300, delayMillis = 50, easing = LinearOutSlowInEasing ), label = "tween delay" )
Więcej informacji znajdziesz w sekcji Easing (Zmiękczanie).
Animowanie do określonych wartości w określonych momentach za pomocą keyframes
keyframes
animuje się na podstawie wartości stanu określonych w różnych znacznikach czasu w okresie trwania animacji. W dowolnym momencie wartość animacji będzie interpolowana między dwiema wartościami klatek kluczowych. W przypadku każdego z tych klatek kluczowych można określić wygładzanie, aby wyznaczyć krzywą interpolacji.
Określanie wartości w momencie 0 ms i w momencie trwania jest opcjonalne. Jeśli nie określisz tych wartości, domyślnie będą to odpowiednio wartości początkowe i końcowe animacji.
val value by animateFloatAsState( targetValue = 1f, animationSpec = keyframes { durationMillis = 375 0.0f at 0 using LinearOutSlowInEasing // for 0-15 ms 0.2f at 15 using FastOutLinearInEasing // for 15-75 ms 0.4f at 75 // ms 0.4f at 225 // ms }, label = "keyframe" )
Płynne animowanie między klatkami kluczowymi za pomocą funkcji keyframesWithSplines
Aby utworzyć animację, która podczas przechodzenia między wartościami porusza się po gładkiej krzywej, możesz użyć specyfikacji animacji keyframesWithSplines
zamiast keyframes
.
val offset by animateOffsetAsState( targetValue = Offset(300f, 300f), animationSpec = keyframesWithSpline { durationMillis = 6000 Offset(0f, 0f) at 0 Offset(150f, 200f) atFraction 0.5f Offset(0f, 100f) atFraction 0.7f } )
Klatki kluczowe oparte na splajnach są szczególnie przydatne w przypadku dwuwymiarowego ruchu elementów na ekranie.
Poniższe filmy pokazują różnice między keyframes
a keyframesWithSpline
przy tym samym zestawie współrzędnych x i y, po których powinien poruszać się okrąg.
keyframes
|
keyframesWithSplines
|
---|---|
Jak widać, klatki kluczowe oparte na splajnach zapewniają płynniejsze przejścia między punktami, ponieważ wykorzystują krzywe Beziera do płynnego animowania elementów. Ta specyfikacja jest przydatna w przypadku gotowej animacji. Jeśli jednak pracujesz z punktami sterowanymi przez użytkownika, lepiej używać sprężyn, aby uzyskać podobną płynność między punktami, ponieważ można je przerwać.
Powtarzanie animacji za pomocą repeatable
repeatable
uruchamia animację opartą na czasie trwania (np. tween
lub keyframes
)repeatable
wielokrotnie, aż osiągnie określoną liczbę iteracji. Możesz przekazać parametr repeatMode
, aby określić, czy animacja ma być powtarzana od początku (RepeatMode.Restart
) czy od końca (RepeatMode.Reverse
).
val value by animateFloatAsState( targetValue = 1f, animationSpec = repeatable( iterations = 3, animation = tween(durationMillis = 300), repeatMode = RepeatMode.Reverse ), label = "repeatable spec" )
Powtarzanie animacji w nieskończoność za pomocą infiniteRepeatable
Funkcja infiniteRepeatable
działa podobnie jak repeatable
, ale powtarza się w nieskończoność.
val value by animateFloatAsState( targetValue = 1f, animationSpec = infiniteRepeatable( animation = tween(durationMillis = 300), repeatMode = RepeatMode.Reverse ), label = "infinite repeatable" )
W testach z użyciem
ComposeTestRule
animacje z użyciem infiniteRepeatable
nie są uruchamiane. Komponent zostanie wyrenderowany przy użyciu wartości początkowej każdej animowanej wartości.
Natychmiastowe przejście do wartości końcowej za pomocą: snap
snap
to specjalny AnimationSpec
, który natychmiast przełącza wartość na wartość końcową. Możesz określić delayMillis
, aby opóźnić rozpoczęcie animacji.
val value by animateFloatAsState( targetValue = 1f, animationSpec = snap(delayMillis = 50), label = "snap spec" )
Ustawianie niestandardowej funkcji łagodzenia
Operacje oparte na czasie trwania AnimationSpec
(np. tween
lub keyframes
) używają Easing
do dostosowywania ułamka animacji. Dzięki temu animowana wartość może przyspieszać i zwalniać, zamiast poruszać się ze stałą szybkością. Ułamek to wartość z zakresu od 0 (początek) do 1,0 (koniec) wskazująca bieżący punkt animacji.
Funkcja łagodzenia to funkcja, która przyjmuje wartość ułamkową z zakresu od 0 do 1,0 i zwraca liczbę zmiennoprzecinkową. Zwracana wartość może wykraczać poza granicę, aby odzwierciedlać przekroczenie lub niedobór. Niestandardowe wygładzanie można utworzyć za pomocą kodu poniżej.
val CustomEasing = Easing { fraction -> fraction * fraction } @Composable fun EasingUsage() { val value by animateFloatAsState( targetValue = 1f, animationSpec = tween( durationMillis = 300, easing = CustomEasing ), label = "custom easing" ) // …… }
Funkcja Pisanie ma kilka wbudowanych funkcji Easing
, które obejmują większość przypadków użycia.
Więcej informacji o tym, jakiego rodzaju wygładzania używać w zależności od sytuacji, znajdziesz w artykule Szybkość – Material Design.
FastOutSlowInEasing
LinearOutSlowInEasing
FastOutLinearEasing
LinearEasing
CubicBezierEasing
- Pokaż więcej
Animowanie niestandardowych typów danych przez konwertowanie na AnimationVector
i z AnimationVector
Większość interfejsów API animacji w Compose domyślnie obsługuje Float
, Color
, Dp
i inne podstawowe typy danych jako wartości animacji, ale czasami trzeba animować inne typy danych, w tym niestandardowe. Podczas animacji każda animowana wartość jest reprezentowana jako AnimationVector
. Wartość jest konwertowana na AnimationVector
i odwrotnie przez odpowiedni TwoWayConverter
, dzięki czemu podstawowy system animacji może obsługiwać je w jednolity sposób. Na przykład Int
jest reprezentowany jako AnimationVector1D
, który zawiera pojedynczą wartość zmiennoprzecinkową.
TwoWayConverter
dla Int
wygląda tak:
val IntToVector: TwoWayConverter<Int, AnimationVector1D> = TwoWayConverter({ AnimationVector1D(it.toFloat()) }, { it.value.toInt() })
Color
to w zasadzie zestaw 4 wartości: czerwonej, zielonej, niebieskiej i alfa, więc
Color
jest przekształcana w AnimationVector4D
, która zawiera 4 wartości zmiennoprzecinkowe. W ten sposób każdy typ danych używany w animacjach jest konwertowany na AnimationVector1D
, AnimationVector2D
, AnimationVector3D
lub AnimationVector4D
w zależności od jego wymiarowości. Dzięki temu różne komponenty obiektu mogą być animowane niezależnie od siebie, a każdy z nich ma własne śledzenie prędkości. Wbudowane konwertery podstawowych typów danych są dostępne za pomocą konwerterów takich jak Color.VectorConverter
lub Dp.VectorConverter
.
Jeśli chcesz dodać obsługę nowego typu danych jako wartości animacji, możesz utworzyć własny TwoWayConverter
i przekazać go do interfejsu API. Możesz na przykład użyć animateValueAsState
do animowania niestandardowego typu danych w ten sposób:
data class MySize(val width: Dp, val height: Dp) @Composable fun MyAnimation(targetSize: MySize) { val animSize: MySize by animateValueAsState( targetSize, TwoWayConverter( convertToVector = { size: MySize -> // Extract a float value from each of the `Dp` fields. AnimationVector2D(size.width.value, size.height.value) }, convertFromVector = { vector: AnimationVector2D -> MySize(vector.v1.dp, vector.v2.dp) } ), label = "size" ) }
Poniżej znajdziesz listę wbudowanych VectorConverter
:
Color.VectorConverter
Dp.VectorConverter
Offset.VectorConverter
Int.VectorConverter
Float.VectorConverter
IntSize.VectorConverter
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony.
- Animacje oparte na wartościach
- Iteracyjne tworzenie kodu {:#iterative-code-dev }
- Animacje w Compose