System animacji właściwości to solidna struktura, która umożliwia pozwala animować niemal wszystko. Możesz zdefiniować animację, aby z czasem zmienić dowolną właściwość obiektu, niezależnie od tego, czy wyświetla się na ekranie, czy nie. Animacja właściwości zmienia (pola w obiekcie) w określonym czasie. Aby coś animować, musisz określić parametr właściwość obiektu, którą chcesz animować, taką jak pozycja obiektu na ekranie, czas trwania obiektu dla których ma być animowany i jakie wartości mają być animowane.
System animacji właściwości pozwala określić następujące cechy obiektu animacja:
- Czas trwania: możesz podać czas trwania animacji. Domyślna długość to 300 ms.
- Interpolacja czasu: możesz określić sposób obliczania wartości właściwości jako obecnego czasu trwania animacji.
- Liczba powtórzeń i zachowanie: możesz określić, czy animacja ma być powtarzana, gdy dochodzi do końca czasu trwania animacji i ile razy ma zostać powtórzona. Możesz też określ, czy animacja ma być odtwarzana wstecz. ustawianie odwrotnego odtwarzania, animacja w przód i w tył, aż zostanie osiągnięta odpowiednia liczba powtórzeń.
- Zestawy animacji: można grupować animacje w logiczne zbiory, które są odtwarzane razem lub sekwencyjnie lub po określonych opóźnieniach.
- Opóźnienie odświeżania klatki: możesz określić, jak często mają być odświeżane klatki animacji. domyślnie jest ustawione odświeżanie co 10 ms, ale aplikacja może odświeżać klatki z szybkością ostatecznie zależy od tego, jak duży jest ruch w systemie i jak szybko może on obsługiwać minutnik.
Pełny przykład animacji właściwości znajdziesz w sekcji
Klasa ChangeColor
w elemencie Customprzejść
znajdziesz na GitHubie.
Jak działa animacja właściwości
Najpierw spójrzmy na prosty przykład, jak działa animacja. Rysunek 1 przedstawia
hipotetyczny obiekt animowany za pomocą właściwości x
, która reprezentuje
w poziomie na ekranie. Czas trwania animacji jest ustawiony na 40 ms oraz odległość
ma 40 pikseli. Co 10 ms (czyli domyślna częstotliwość odświeżania klatek) obiekt przesuwa się
w poziomie o 10 pikseli. Po 40 ms animacja zatrzymuje się, a obiekt kończy się na
pozycja w poziomie 40. To jest przykład animacji z interpolacją liniową, co oznacza
porusza się ze stałą prędkością.
![](https://developer.android.google.cn/static/images/animation/animation-linear.png?authuser=0000&hl=pl)
Rysunek 1. Przykład animacji liniowej
Możesz też określić animacje z interpolacją nieliniową. Rysunek 2 przedstawia hipotetyczny obiekt, który przyspiesza na początku animacji i zwalnia na na koniec animacji. Obiekt nadal przesuwa się o 40 pikseli w czasie 40 ms, ale nie liniowo. W na początku animacja przyspiesza do połowy, a potem zwalnia do końca animacji. Jak widać na rys. 2, przebyta odległość na początku i na końcu animacji jest mniejszy niż w środku.
![](https://developer.android.google.cn/static/images/animation/animation-nonlinear.png?authuser=0000&hl=pl)
Rysunek 2. Przykład animacji nieliniowej
Przyjrzyjmy się bliżej kluczowym komponentom systemu animacji właściwości oblicza animacje takie jak te pokazane powyżej. Rysunek 3 przedstawia główne klasy współdziałają ze sobą.
![](https://developer.android.google.cn/static/images/animation/valueanimator.png?authuser=0000&hl=pl)
Rysunek 3. Sposób obliczania animacji
Obiekt ValueAnimator
śledzi czas animacji,
takich jak czas trwania animacji i bieżącą wartość właściwości,
ani tworzyć animacji.
Pole ValueAnimator
zawiera znacznik TimeInterpolator
, który definiuje interpolację animacji, i zasadę TypeEvaluator
, która określa sposób obliczania wartości dla właściwości
animowanego. Na przykład na rys. 2 wartością TimeInterpolator
będzie
AccelerateDecelerateInterpolator
, a TypeEvaluator
to IntEvaluator
.
Aby rozpocząć animację, utwórz ValueAnimator
i dodaj do niego atrybut
wartość początkową i końcową właściwości, którą chcesz animować, oraz czas trwania parametru
animację. Gdy wywołujesz start()
, animację
Podczas całej animacji ValueAnimator
oblicza ułamek, który upłynął
od 0 do 1, w zależności od czasu trwania animacji i czasu, jaki upłynął.
ułamek czasu trwania przedstawia procent czasu ukończenia animacji, 0 oznacza 0%
a 1 oznacza 100%. Na przykład na ilustracji 1 ułamek czasu, który upłynął w czasie t = 10 ms, wyniesie 0,25.
ponieważ łączny czas trwania to t = 40 ms.
Gdy funkcja ValueAnimator
zakończy obliczanie ułamka, funkcja
wywołuje aktualnie ustawioną funkcję TimeInterpolator
, aby obliczyć
ułamek interpolowany. Interpolowany ułamek mapuje upływ czasu na nowy
biorąc pod uwagę ustawioną interpolację czasową. Na przykład na rys. 2
ponieważ animacja powoli przyspiesza, interpolowany ułamek, około 0,15, jest mniejszy niż
upływ czasu, 0,25, przy t = 10 ms. Na rys. 1 interpolowany ułamek jest zawsze taki sam jak
upływ czasu.
Podczas obliczania interpolowanego ułamka funkcja ValueAnimator
wywołuje
odpowiednią TypeEvaluator
, aby obliczyć wartość argumentu
animowaną właściwość, na podstawie interpolowanego ułamka, wartości początkowej
wartość końcową animacji. Na przykład na rys .2 interpolowany ułamek wynosił 0,15 w t =
10 ms, więc jego wartość w tym momencie wynosi 0,15 × (40 – 0), czyli 6.
Czym animacja właściwości różni się od animacji widoku
System animacji widoku umożliwia animowanie tylko elementu View
więc jeśli chcesz animować obiekty inne niż View
, musisz zaimplementować
za pomocą własnego kodu. System animacji widoku jest również ograniczony, ponieważ
ujawnia kilka aspektów obiektu View
animacji, takich jak skalowanie
możesz zmienić widok, ale nie zmienić koloru tła.
Inną wadą systemu animacji widoku jest to, że zmienia się on tylko wtedy, gdy tag Narysowano widok, a nie sam widok. Jeśli na przykład animujesz przycisk do poruszania się na ekranie, przycisk będzie prawidłowo rysowany, ale miejsce, w którym można kliknąć przycisk nie zmienia się, więc trzeba wprowadzić własną logikę, aby to umożliwić.
W systemie animacji właściwości te ograniczenia są całkowicie usuwane, dowolną właściwość dowolnego obiektu (obiekty View i inne niż widoki), a sam obiekt zostaje rzeczywiście zmodyfikowany. System animacji właściwości jest też bardziej solidny pod względem animacji. Na przypisujesz animatorów do właściwości, które mają być animowane, takich jak kolor, położenie lub rozmiar i mogą definiować takie aspekty animacji, jak interpolacja synchronizacji wielu animatorów.
Jednak konfiguracja systemu animacji widoku jest krótsza i wymaga mniej kodu do napisania. Jeśli animacja widoku spełnia wszystkie wymagania, albo jeśli istniejący kod został już działa zgodnie z oczekiwaniami, nie ma potrzeby używania systemu animacji właściwości. Może też użycie obu systemów animacji w różnych sytuacjach ma sens w różnych sytuacjach.
Omówienie interfejsu API
Większość interfejsów API systemu animacji właściwości znajdziesz w języku: android.animation
. Ponieważ system animacji widoku już
definiuje wiele interpolatorów w argumencie android.view.animation
, możesz użyć
z interpolatorami w systemie animacji właściwości. W tabelach poniżej opisujemy główne
komponentów systemu animacji właściwości.
Klasa Animator
zapewnia podstawową strukturę tworzenia
ani animacji. Zwykle nie używasz tej klasy bezpośrednio, ponieważ zapewnia ona tylko minimalną
tę funkcję należy rozszerzyć, aby w pełni obsługiwać animowanie wartości. Poniżej
podklasy rozszerzają Animator
:
Tabela 1. Animatorzy
Kategoria | Opis |
---|---|
ValueAnimator |
Główny mechanizm czasowy animacji właściwości, który również oblicza wartości dla
właściwości, która ma być animowana. Ma wszystkie główne funkcje służące do obliczania animacji
i zawierają szczegółowe informacje o czasie każdej animacji, a także informacje o tym, czy
powtórzenia animacji, detektory odbierające zdarzenia aktualizacji oraz możliwość ustawiania
typów do oceny. Animowanie właściwości składa się z dwóch elementów: obliczanie wartości animacji
i ustawianie ich dla obiektu i właściwości, które są animowane. ValueAnimator nie wykonuje drugiego fragmentu, więc posłuchaj
dla aktualizacji wartości obliczonych przez ValueAnimator i
i modyfikować obiekty, które mają być animowane za pomocą własnej logiki. Zapoznaj się z sekcją na temat
Więcej informacji znajdziesz w artykule Animating with ValueAnimator. |
ObjectAnimator |
Podklasa klasy ValueAnimator , która umożliwia ustawienie wartości docelowej
obiektu i obiektu do animacji. Ta klasa odpowiednio aktualizuje właściwość, gdy:
oblicza nową wartość animacji. Czego chcesz użyć
ObjectAnimator przeważnie,
bo znacznie ułatwia to animowanie wartości na obiektach docelowych. Pamiętaj jednak:
czasami lepiej jest używać usługi ValueAnimator bezpośrednio, ponieważ usługa ObjectAnimator ma jeszcze kilka ograniczeń, takich jak
metody akcesora, które będą obecne w obiekcie docelowym. |
AnimatorSet |
Zapewnia mechanizm grupowania animacji, tak aby były uruchamiane relacji między sobą. Możesz ustawić odtwarzanie animacji po kolei, po kolei lub później. określonego opóźnienia. Więcej informacji znajdziesz w sekcji Choreografia wielu osób za pomocą zestawów animacji. |
Weryfikatorzy informują system animacji właściwości, jak obliczyć wartości danej
usłudze. Zbierają dane o czasie dostarczone przez Animator
klasy, wartość początkową i końcową animacji oraz obliczają animowane wartości właściwości
na podstawie tych danych. System animacji właściwości udostępnia te weryfikatory:
Tabela 2. Weryfikatorzy
Klasa/interfejs | Opis |
---|---|
IntEvaluator |
Domyślny tester do obliczania wartości właściwości int . |
FloatEvaluator |
Domyślny tester do obliczania wartości właściwości float . |
ArgbEvaluator |
Domyślny weryfikator do obliczania wartości reprezentowanych właściwości koloru pod postacią wartości szesnastkowych. |
TypeEvaluator |
Interfejs, który pozwala utworzyć własnego testera. Jeśli animujesz element
właściwością obiektu, która nie jest wartością int , float ani kolorem,
musisz zaimplementować interfejs TypeEvaluator , aby określić,
do obliczenia animowanych wartości właściwości obiektu. Możesz też określić niestandardową wartość TypeEvaluator dla atrybutów int , float i koloru.
, jeśli chcesz przetwarzać te typy w inny sposób niż domyślne.
Więcej informacji znajdziesz w sekcji Korzystanie z narzędzia TypeEvaluator
na temat tego, jak napisać weryfikatora. |
Interpolator czasowy określa sposób obliczania konkretnych wartości w animacji jako wartości
funkcji czasu. Możesz na przykład określić, że animacje mają następować liniowo w całym
czyli animację przesuwa się równomiernie przez cały czas. Można też ją określić,
aby użyć czasu nieliniowego, np. przyspieszania na początku i zwalniania na początku
na koniec animacji. Tabela 3 opisuje interpolatory zawarte w funkcji android.view.animation
. Jeśli żaden z podanych interpolatorów nie pasuje
zaimplementuj interfejs TimeInterpolator
i utwórz własny. Więcej informacji o tworzeniu niestandardowych wartości znajdziesz w artykule Używanie interpolatorów.
i interpolatorze.
Tabela 3. Interpolatory
Klasa/interfejs | Opis |
---|---|
AccelerateDecelerateInterpolator |
Interpolator, którego szybkość zmiany zaczyna się i kończy powoli, ale przyspiesza do środka. |
AccelerateInterpolator |
Interpolator, którego tempo zmian zaczyna się powoli, a potem przyspiesza. |
AnticipateInterpolator |
Interpolator, którego zmiana zaczyna się od tyłu, a potem przesuwa się do przodu. |
AnticipateOvershootInterpolator |
Interpolator, którego zmiana rozpoczyna się wstecz, przesuwa do przodu i przebiega do wartości docelowej, a następnie wraca do ostatecznej wartości. |
BounceInterpolator |
Interpolator, którego zmiana jest odbijana na końcu. |
CycleInterpolator |
Interpolator, którego animacja powtarza się przez określoną liczbę cykli. |
DecelerateInterpolator |
Interpolator, którego tempo zmian szybko rozpoczyna się, zwalnia. |
LinearInterpolator |
Interpolator, którego szybkość zmian jest stała. |
OvershootInterpolator |
Interpolator, którego zmiana przesuwa się do przodu i przekracza ostatnią wartość, wrócą. |
TimeInterpolator |
Interfejs umożliwiający wdrożenie własnego interpolatora. |
Animacja za pomocą ValueAnimator
Klasa ValueAnimator
pozwala animować pewne wartości określonego typu w polu
czas trwania animacji, określając zestaw int
, float
lub kolor.
wartości animacji. Otrzymujesz ValueAnimator
, dzwoniąc do jednego z
jego metody fabryczne: ofInt()
, ofFloat()
lub ofObject()
. Na przykład:
Kotlin
ValueAnimator.ofFloat(0f, 100f).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f); animation.setDuration(1000); animation.start();
W tym kodzie ValueAnimator
rozpoczyna obliczanie wartości funkcji
od 0 do 100 animacji przez okres 1000 ms, gdy działa metoda start()
.
Możesz też określić niestandardowy typ animacji, wykonując te czynności:
Kotlin
ValueAnimator.ofObject(MyTypeEvaluator(), startPropertyValue, endPropertyValue).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue); animation.setDuration(1000); animation.start();
W tym kodzie ValueAnimator
rozpoczyna obliczanie wartości funkcji
animacji między startPropertyValue
a endPropertyValue
za pomocą funkcji
logika dostarczana przez MyTypeEvaluator
na czas trwania 1000 ms, gdy działa metoda start()
.
Możesz użyć wartości animacji, dodając element
AnimatorUpdateListener
do obiektu ValueAnimator
, jak pokazano w
ten kod:
Kotlin
ValueAnimator.ofObject(...).apply { ... addUpdateListener { updatedAnimation -> // You can use the animated value in a property that uses the // same type as the animation. In this case, you can use the // float value in the translationX property. textView.translationX = updatedAnimation.animatedValue as Float } ... }
Java
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator updatedAnimation) { // You can use the animated value in a property that uses the // same type as the animation. In this case, you can use the // float value in the translationX property. float animatedValue = (float)updatedAnimation.getAnimatedValue(); textView.setTranslationX(animatedValue); } });
W: onAnimationUpdate()
możesz uzyskać dostęp do zaktualizowanej wartości animacji i użyć jej we właściwości
jeden z Twoich widoków. Więcej informacji o słuchaczach znajdziesz w sekcji
Detektory animacji.
Animacja przy użyciu ObjectAnimator
ObjectAnimator
to podklasa klasy ValueAnimator
(omówiona w poprzedniej sekcji) łącząca sygnatury czasowe
mechanizmu i obliczania wartości ValueAnimator
z możliwością
animowanie nazwanej właściwości obiektu docelowego. To znacznie ułatwia animowanie obiektów,
nie muszą już implementować: ValueAnimator.AnimatorUpdateListener
,
ponieważ właściwość animowana jest aktualizowana automatycznie.
Tworzenie instancji ObjectAnimator
jest podobne do ValueAnimator
, ale dodatkowo musisz podać obiekt i nazwę jego właściwości (np.
ciąg znaków) wraz z wartościami, które będą animowane między:
Kotlin
ObjectAnimator.ofFloat(textView, "translationX", 100f).apply { duration = 1000 start() }
Java
ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f); animation.setDuration(1000); animation.start();
Aby mieć ObjectAnimator
właściwości aktualizacji
musisz wykonać te czynności:
- Animowana właściwość obiektu, którą chcesz animować, musi mieć funkcję ustawiającą (w przypadku wielbłąda) w postaci
set<PropertyName>()
PonieważObjectAnimator
automatycznie aktualizuje właściwość podczas animacji, musi mieć dostęp do właściwości metody określania. Jeśli na przykład nazwa usługi tofoo
, musisz mają metodęsetFoo()
. Jeśli ta metoda ustawienia nie istnieje, są dostępne opcje:- Dodaj metodę ustawiającą do klasy, jeśli masz do tego uprawnienia.
- Użyj klasy kodu, który możesz zmieniać i który powinien otrzymywać z prawidłową metodą ustawiającą i przekazać ją do pierwotnego obiektu.
- Użyj w zamian zasady
ValueAnimator
.
- Jeśli określisz tylko jedną wartość parametru
values...
w jednej z metod fabrykiObjectAnimator
, przyjmuje się, że jest to wartość końcowa parametru animację. Dlatego właściwość obiektu, którą animujesz, musi mieć funkcję pobierania. służąca do uzyskania początkowej wartości animacji. Funkcja pobierania musi być w funkcji formatget<PropertyName>()
. Jeśli na przykład nazwa właściwości tofoo
, musisz mieć metodęgetFoo()
. - Metody getter (w razie potrzeby) i metody ustawiania właściwości, którą animujesz, muszą
działają na tym samym typie co wartości początkowa i końcowa określona w funkcji
ObjectAnimator
. Na przykład:targetObject.setPropName(float)
itargetObject.getPropName()
jeśli utworzysz następujący elementObjectAnimator
:ObjectAnimator.ofFloat(targetObject, "propName", 1f)
- W zależności od właściwości lub obiektu, które animujesz, konieczne może być wywołanie metody
invalidate()
w widoku danych, by wymusić ponowne przerysowanie ekranu za pomocą animowanych wartości. Robi się to wonAnimationUpdate()
oddzwanianie. Na przykład animowanie właściwości koloru obiektu Drawable powoduje zaktualizowanie tylko atrybutu po ponownym wyświetleniu obiektu. Wszystkie kreatory właściwości w widoku danych, takie jaksetAlpha()
isetTranslationX()
unieważnia widok, więc nie trzeba unieważniać go przy wywoływaniu tych z nowymi wartościami. Więcej informacji o słuchaczach znajdziesz w sekcji Detektory animacji.
Tworzenie choreografii do wielu animacji za pomocą narzędzia AnimatorSet
Często trzeba odtworzyć animację w zależności od tego, kiedy rozpocznie się inna animacja,
na ich końcu. System Android umożliwia łączenie animacji w elementy AnimatorSet
, dzięki którym można określić, czy mają się rozpoczynać.
jednocześnie, sekwencyjnie lub po określonym opóźnieniu. Obiekty AnimatorSet
możesz też zagnieżdżać w sobie.
Ten fragment kodu odtwarza Animator
w następujący sposób:
- Odtwarzam
bounceAnim
. - Odtwarza:
squashAnim1
,squashAnim2
,stretchAnim1
istretchAnim2
. - Odtwarzam
bounceBackAnim
. - Odtwarzam
fadeAnim
.
Kotlin
val bouncer = AnimatorSet().apply { play(bounceAnim).before(squashAnim1) play(squashAnim1).with(squashAnim2) play(squashAnim1).with(stretchAnim1) play(squashAnim1).with(stretchAnim2) play(bounceBackAnim).after(stretchAnim2) } val fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply { duration = 250 } AnimatorSet().apply { play(bouncer).before(fadeAnim) start() }
Java
AnimatorSet bouncer = new AnimatorSet(); bouncer.play(bounceAnim).before(squashAnim1); bouncer.play(squashAnim1).with(squashAnim2); bouncer.play(squashAnim1).with(stretchAnim1); bouncer.play(squashAnim1).with(stretchAnim2); bouncer.play(bounceBackAnim).after(stretchAnim2); ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(bouncer).before(fadeAnim); animatorSet.start();
Detektory animacji
Za pomocą detektorów opisanych poniżej możesz nasłuchiwać ważnych zdarzeń w czasie trwania animacji.
Animator.AnimatorListener
onAnimationStart()
– wywoływane po rozpoczęciu animacji.onAnimationEnd()
– Wywoływane po zakończeniu animacji.onAnimationRepeat()
– wywoływana, gdy animacja się powtarza.onAnimationCancel()
– wywoływane po anulowaniu animacji. Anulowana animacja wywołuje też:onAnimationEnd()
, niezależnie od sposobu ich zakończenia.
ValueAnimator.AnimatorUpdateListener
-
onAnimationUpdate()
– wywoływane przy każdej klatce animacji. Posłuchaj tego zdarzenia na: użyj obliczonych wartości wygenerowanych przezValueAnimator
podczas animację. Aby użyć tej wartości, wyślij zapytanie do obiektuValueAnimator
przekazywane do zdarzenia, by uzyskać bieżącą animowaną wartość za pomocą metodygetAnimatedValue()
. Wdrożenie Jeśli używaszValueAnimator
, wymagany jest detektor.W zależności od animowanej właściwości lub obiektu może być konieczne wywołanie
invalidate()
w widoku danych, aby wymusić stosowanie danego obszaru ekranu, aby ponownie wczytać się z nowymi animowanymi wartościami. Na przykład animowanie elementu Właściwość color obiektu Drawable aktualizuje ekran tylko wtedy, gdy ten obiekt i spowoduje to ponowne zarysowanie. Wszystkie osoby tworzące nieruchomości w widoku danych na przykładsetAlpha()
isetTranslationX()
unieważnia widok Dzięki temu nie trzeba unieważniać widoku danych przy wywoływaniu tych metod z nowymi wartościami.
-
Możesz przedłużyć zajęcia AnimatorListenerAdapter
zamiast
nie implementujesz interfejsu Animator.AnimatorListener
.
chcesz wdrożyć wszystkie metody interfejsu Animator.AnimatorListener
za pomocą prostego interfejsu online. Klasa AnimatorListenerAdapter
zawiera puste
implementacji metod, które można zastąpić.
Na przykład ten fragment kodu tworzy AnimatorListenerAdapter
tylko za onAnimationEnd()
wywołanie zwrotne:
Kotlin
ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply { duration = 250 addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { balls.remove((animation as ObjectAnimator).target) } }) }
Java
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); fadeAnim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { balls.remove(((ObjectAnimator)animation).getTarget()); }
Animuj zmiany układu w obiektach ViewGroup
System animacji właściwości umożliwia animowanie zmian obiektów ViewGroup. a także pozwalają w łatwy sposób animować same obiekty View.
Możesz animować zmiany układu w grupie widoków za pomocą
LayoutTransition
zajęcia. Widoki w grupie widoków
pojawiają się i znikają animacje po dodaniu ich do
by usunąć je z grupy widoków lub podczas wywoływania
Metoda setVisibility()
z
VISIBLE
, INVISIBLE
lub
GONE
Pozostałe widoki w grupie widoków
ich nowe pozycje przy dodawaniu lub usuwaniu widoków. Możesz zdefiniować
te animacje w obiekcie LayoutTransition
dzwoniąc pod numer setAnimator()
i przekazywanie obiektu Animator
z jedną z metod
następujące stałe LayoutTransition
:
APPEARING
– flaga wskazująca animację, która jest odtwarzana na elementach, które są które wyświetlają się w kontenerze.CHANGE_APPEARING
– flaga wskazująca animację, która jest odtwarzana na elementach, które są zmienia się z powodu pojawienia się w kontenerze nowego elementu.DISAPPEARING
– flaga wskazująca animację, która jest odtwarzana na elementach, które są znika z kontenera.CHANGE_DISAPPEARING
– flaga wskazująca animację uruchamianą na elementach, które zmienia się, ponieważ element znika z kontenera.
Możesz definiować własne animacje dla tych 4 typów zdarzeń, aby dostosować ich wygląd. przejść do układu strony lub wskazać systemowi animacji, by używał animacji domyślnych.
Aby ustawić wartość atrybutu android:animateLayoutchanges
na true
dla:
ViewGroup wykonuje te czynności:
<LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/verticalContainer" android:animateLayoutChanges="true" />
Ustawienie wartości prawda w atrybucie prawda powoduje automatyczne animowanie widoków danych, które zostały dodane lub usunięte z ViewGroup oraz pozostałych widoków w grupie ViewGroup.
Animacja zmian stanu widoku za pomocą StateListAnimator
Klasa StateListAnimator
pozwala zdefiniować animacje, które działają, gdy
stan widoku zmienia się. Obiekt ten zachowuje się jako otoka
Animator
obiekt, wywołując tę animację, gdy jest określony
zmiany stanu wyświetlania (np. „naciśnięcie” lub „zaznaczenie”).
Element StateListAnimator
można zdefiniować w zasobie XML z rdzeniem
określony przez siebie element <selector>
i elementy podrzędne <item>
,
inny stan widoku zdefiniowany przez klasę StateListAnimator
. Każdy
<item>
zawiera definicję zestawu animacji właściwości.
Na przykład ten plik tworzy animator listy stanów, który zmienia skalę x i y. widoku po naciśnięciu:
res/xml/animate_scale.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- the pressed state; increase x and y size to 150% --> <item android:state_pressed="true"> <set> <objectAnimator android:propertyName="scaleX" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1.5" android:valueType="floatType"/> <objectAnimator android:propertyName="scaleY" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1.5" android:valueType="floatType"/> </set> </item> <!-- the default, non-pressed state; set x and y size to 100% --> <item android:state_pressed="false"> <set> <objectAnimator android:propertyName="scaleX" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1" android:valueType="floatType"/> <objectAnimator android:propertyName="scaleY" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1" android:valueType="floatType"/> </set> </item> </selector>
Aby dołączyć do widoku animator listy stanów, dodaj
android:stateListAnimator
w ten sposób:
<Button android:stateListAnimator="@xml/animate_scale" ... />
Teraz animacje zdefiniowane w polu animate_scale.xml
są używane, gdy przycisk tego przycisku
zmian stanu.
Aby zamiast tego przypisać animator listy stanów do widoku w kodzie, użyj
AnimatorInflater.loadStateListAnimator()
i przypisz animatora do
widoku za pomocą metody View.setStateListAnimator()
.
Zamiast animować właściwości widoku, możesz odtworzyć rysowalną animację między
zmian stanu za pomocą funkcji AnimatedStateListDrawable
.
Niektóre widżety systemowe w
Android 5.0 używa tych animacji domyślnie. Ten przykład pokazuje,
aby zdefiniować AnimatedStateListDrawable
jako zasób XML:
<!-- res/drawable/myanimstatedrawable.xml --> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- provide a different drawable for each state--> <item android:id="@+id/pressed" android:drawable="@drawable/drawableP" android:state_pressed="true"/> <item android:id="@+id/focused" android:drawable="@drawable/drawableF" android:state_focused="true"/> <item android:id="@id/default" android:drawable="@drawable/drawableD"/> <!-- specify a transition --> <transition android:fromId="@+id/default" android:toId="@+id/pressed"> <animation-list> <item android:duration="15" android:drawable="@drawable/dt1"/> <item android:duration="15" android:drawable="@drawable/dt2"/> ... </animation-list> </transition> ... </animated-selector>
Użyj narzędzia TypeEvaluator
Jeśli chcesz animować typ, który jest nieznany systemowi Android, możesz utworzyć własne
używając interfejsu TypeEvaluator
. Typy, które
są rozpoznawane przez system Android to int
, float
, czyli kolor, który jest
obsługiwane przez typy IntEvaluator
, FloatEvaluator
i ArgbEvaluator
weryfikatorami.
TypeEvaluator
ma tylko 1 metodę implementacji
metody evaluate()
. Dzięki temu
używany do zwrócenia odpowiedniej wartości dla właściwości animowanej w tagu
bieżącego punktu animacji. Zajęcia FloatEvaluator
zademonstrują
jak to zrobić:
Kotlin
private class FloatEvaluator : TypeEvaluator<Any> { override fun evaluate(fraction: Float, startValue: Any, endValue: Any): Any { return (startValue as Number).toFloat().let { startFloat -> startFloat + fraction * ((endValue as Number).toFloat() - startFloat) } } }
Java
public class FloatEvaluator implements TypeEvaluator { public Object evaluate(float fraction, Object startValue, Object endValue) { float startFloat = ((Number) startValue).floatValue(); return startFloat + fraction * (((Number) endValue).floatValue() - startFloat); } }
Uwaga: po uruchomieniu funkcji ValueAnimator
(lub ObjectAnimator
) oblicza bieżący ułamek czasu
(wartość od 0 do 1), a następnie oblicza jej wersję interpolowaną w zależności
jakiego interpolatora używasz. Ułamek interpolowany to wartość, jaką TypeEvaluator
otrzymuje przez parametr fraction
, więc
nie trzeba uwzględniać interpolatora przy obliczaniu wartości animowanych.
Korzystanie z interpolatorów
Interpolator określa sposób obliczania konkretnych wartości w animacji jako funkcja obecnie się znajdujesz. Możesz na przykład określić, że animacje będą następować liniowo przez całą animację, co oznacza, że animacja przesuwa się równomiernie przez cały czas. Możesz też określić, które animacje będą używane. w czasie nieliniowym, np. z użyciem przyspieszania lub zwalniania na początku lub końcu animację.
Interpolatory w systemie animacji otrzymują ułamek od animatatorów, które reprezentują
czasu trwania animacji. Interpolator modyfikuje ten ułamek, aby zbiegł się z typem
i animację. System Android udostępnia zestaw typowych interpolatorów w
android.view.animation package
. Jeśli żadna z tych opcji nie pasuje
możesz wdrożyć interfejs TimeInterpolator
i utworzyć
własnych.
Poniżej pokazujemy, jak domyślny interpolator AccelerateDecelerateInterpolator
i LinearInterpolator
obliczają ułamki interpolowane.
LinearInterpolator
nie ma wpływu na ułamek czasu, który upłynął. AccelerateDecelerateInterpolator
przyspiesza do animacji i
zwalnia. Logikę tych interpolatorów definiują następujące metody:
AccelerateDecelerateInterpolator,
Kotlin
override fun getInterpolation(input: Float): Float = (Math.cos((input + 1) * Math.PI) / 2.0f).toFloat() + 0.5f
Java
@Override public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; }
Interpolator liniowy
Kotlin
override fun getInterpolation(input: Float): Float = input
Java
@Override public float getInterpolation(float input) { return input; }
Poniższa tabela przedstawia przybliżone wartości obliczane przez te interpolatory animacji trwających 1000 ms:
Upłynęło: ms | Ułamek czasu/ułamek interpolowany (liniowy) | Ułamek interpolowany (przyspiesz/zwolnij) |
---|---|---|
0 | 0 | 0 |
200 | 0,2 | 0,1 |
400 | 0,4 | 0,345 |
600 | 0,6 | 0,8 |
800 | 0,8 | 0,9 |
1000 | 1 | 1 |
Jak widać w tabeli, LinearInterpolator
zmienia wartości.
z tą samą prędkością, 0,2 na każde 200 ms. AccelerateDecelerateInterpolator
zmienia wartości szybciej niż w przypadku parametru LinearInterpolator
w zakresie od 200 do 600 ms i wolniej od 600 do 600 ms
1000ms.
Określanie klatek kluczowych
Obiekt Keyframe
składa się z pary czas/wartość, która pozwala określić
do określonego stanu w danym momencie animacji. Każda klatka kluczowa może też mieć własne
interpolatorem do sterowania zachowaniem animacji w przedziale czasu między poprzednim
czas klatki kluczowej oraz czas tej klatki kluczowej.
Aby utworzyć instancję obiektu Keyframe
, musisz użyć jednej z fabryk
ofInt()
, ofFloat()
lub ofObject()
, aby uzyskać odpowiedni typ Keyframe
. Następnie dzwonisz
metody fabrycznej ofKeyframe()
do
uzyskać obiekt PropertyValuesHolder
. Mając obiekt, możesz
uzyskać animatora, przekazując obiekt PropertyValuesHolder
obiektu do animacji. Fragment kodu ilustruje, jak to zrobić:
Kotlin
val kf0 = Keyframe.ofFloat(0f, 0f) val kf1 = Keyframe.ofFloat(.5f, 360f) val kf2 = Keyframe.ofFloat(1f, 0f) val pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2) ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation).apply { duration = 5000 }
Java
Keyframe kf0 = Keyframe.ofFloat(0f, 0f); Keyframe kf1 = Keyframe.ofFloat(.5f, 360f); Keyframe kf2 = Keyframe.ofFloat(1f, 0f); PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2); ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation); rotationAnim.setDuration(5000);
Animuj wyświetlenia
System animacji obiektu umożliwia sprawne animowanie obiektów i ofert. kilka zalet w porównaniu do systemu animacji widoku. Widok system animacji przekształcił obiekty View, zmieniając sposób ich rysowania. To było w kontenerze każdego widoku danych, ponieważ sam widok nie miał żadnych właściwości, którymi można by manipulować. W efekcie widok danych był animowany, ale nie spowodował zmian w samym obiekcie widoku. Ten doprowadziło do zachowania, takiego jak obiekt wciąż istniał w pierwotnej lokalizacji, mimo że został narysowanych w innym miejscu na ekranie. W Androidzie 3.0 nowe usługi i odpowiadające im Aby wyeliminować tę wadę, dodano metody pobierania i ustawiania.
System animacji właściwości.
mogą animować widoki na ekranie, zmieniając rzeczywiste właściwości obiektów widoku. W
dodawanie, Widok automatycznie wywołuje też funkcję invalidate()
odświeża ekran po każdej zmianie jego właściwości. Nowe właściwości klasy View
, które ułatwiają tworzenie animacji właściwości, to:
translationX
itranslationY
: te właściwości określają, gdzie element Widok jest położony jako delta od współrzędnych lewego i górnego, określone przez jego układ kontenera.rotation
,rotationX
irotationY
: te usługi sterować obrotem w 2D (usługarotation
) i w 3D wokół punktu obrotu.scaleX
iscaleY
: te właściwości sterują skalowaniem 2D obiektu Widok wokół punktu obrotu.pivotX
ipivotY
: te właściwości kontrolują lokalizację punktu przestawnego, wokół którego odbywają się przekształcenia obrotu i skalowania. Domyślnie okrąg znajduje się na środku obiektu.x
iy
: to proste właściwości użytkowe opisujące ostatecznych położenia widoku w jego kontenerze, jako sumy wartości dla lewego i górnego rogu oraz przesunięcieX i przesunięcieY.alpha
: reprezentuje przezroczystość w wersji alfa w widoku danych. Ta wartość wynosi 1 (nieprzezroczyste). domyślnie, gdzie wartość 0 oznacza pełną przezroczystość (niewidoczną).
Aby animować właściwość obiektu View, np. jego kolor lub wartość obrotu, wystarczy należy utworzyć animator właściwości i określić właściwość widoku, która ma być ani animacji. Na przykład:
Kotlin
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f)
Java
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
Więcej informacji na temat tworzenia animacji za pomocą tagów ValueAnimator i ObjectAnimator.
Animacja za pomocą ViewpropertyAnimator
ViewPropertyAnimator
umożliwia proste animowanie kilku
właściwości klasy View
równolegle, przy użyciu jednego bazowego Animator
obiektu. Zachowuje się jak ObjectAnimator
, ponieważ modyfikuje
domyślnych wartości właściwości widoku, ale działa efektywniej, gdy animujesz wiele właściwości w
raz. Dodatkowo, korzystając z kodu ViewPropertyAnimator
,
były bardziej zwięzłe i czytelne. Poniższe fragmenty kodu pokazują różnice w stosowaniu
ObjectAnimator
obiekty, jeden
ObjectAnimator
oraz ViewPropertyAnimator
, gdy
jednocześnie animując właściwości x
i y
widoku.
Wiele obiektów ObjectAnimator
Kotlin
val animX = ObjectAnimator.ofFloat(myView, "x", 50f) val animY = ObjectAnimator.ofFloat(myView, "y", 100f) AnimatorSet().apply { playTogether(animX, animY) start() }
Java
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f); ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f); AnimatorSet animSetXY = new AnimatorSet(); animSetXY.playTogether(animX, animY); animSetXY.start();
One ObjectAnimator,
Kotlin
val pvhX = PropertyValuesHolder.ofFloat("x", 50f) val pvhY = PropertyValuesHolder.ofFloat("y", 100f) ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start()
Java
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f); ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start();
ViewPropertyAnimator
Kotlin
myView.animate().x(50f).y(100f)
Java
myView.animate().x(50f).y(100f);
Szczegółowe informacje o aplikacji ViewPropertyAnimator
znajdziesz na odpowiednich stronach dla deweloperów aplikacji na Androida
blog
post.
Deklarowanie animacji w pliku XML
System animacji właściwości umożliwia deklarowanie animacji właściwości za pomocą kodu XML, zamiast wykonywać w sposób zautomatyzowany. Gdy zdefiniujesz animacje w formacie XML, możesz je łatwo ponownie wykorzystać. w wielu aktywnościach i łatwiej edytować sekwencję animacji.
Aby odróżnić pliki animacji korzystające z interfejsów API nowych właściwości od tych, które korzystają z metody
starszą platformę view animacji,
od Androida 3.1 musisz zapisać pliki XML animacji właściwości w katalogu res/animator/
.
Poniższe klasy animacji właściwości obsługują deklarację XML z atrybutami następujące tagi XML:
ValueAnimator
–<animator>
ObjectAnimator
–<objectAnimator>
AnimatorSet
–<set>
Żeby znaleźć atrybuty, których możesz użyć w deklaracji XML, zapoznaj się z sekcją Animacje . Poniższy przykład odtwarza 2 zestawy animacji obiektu sekwencyjnie, przy czym pierwszy zagnieżdżony zestaw odtwarza razem dwie animacje obiektów:
<set android:ordering="sequentially"> <set> <objectAnimator android:propertyName="x" android:duration="500" android:valueTo="400" android:valueType="intType"/> <objectAnimator android:propertyName="y" android:duration="500" android:valueTo="300" android:valueType="intType"/> </set> <objectAnimator android:propertyName="alpha" android:duration="500" android:valueTo="1f"/> </set>
Aby uruchomić tę animację, musisz zwiększyć zasoby XML w kodzie do obiektu AnimatorSet
, a następnie ustawić obiekty docelowe dla wszystkich animacji
przed uruchomieniem zestawu animacji. Wywołanie setTarget()
ustawia dla wszystkich użytkowników jeden obiekt docelowy dla wszystkich elementów podrzędnych obiektu AnimatorSet
. Jak to zrobić:
Kotlin
(AnimatorInflater.loadAnimator(myContext, R.animator.property_animator) as AnimatorSet).apply { setTarget(myObject) start() }
Java
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.animator.property_animator); set.setTarget(myObject); set.start();
ValueAnimator
możesz również zadeklarować w pliku XML jako
w tym przykładzie:
<animator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:valueType="floatType" android:valueFrom="0f" android:valueTo="-100f" />
Aby użyć poprzedniego elementu ValueAnimator
w kodzie, musisz
musi rozszerzać obiekt, dodać parametr
AnimatorUpdateListener
,
pobrać zaktualizowaną wartość animacji i użyć jej we właściwości jednego z widoków,
jak w tym kodzie:
Kotlin
(AnimatorInflater.loadAnimator(this, R.animator.animator) as ValueAnimator).apply { addUpdateListener { updatedAnimation -> textView.translationX = updatedAnimation.animatedValue as Float } start() }
Java
ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator); xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator updatedAnimation) { float animatedValue = (float)updatedAnimation.getAnimatedValue(); textView.setTranslationX(animatedValue); } }); xmlAnimator.start();
Informacje o składni XML służącej do definiowania właściwości animacji znajdziesz w sekcji Animacje .
Potencjalny wpływ na wydajność interfejsu
Animatory, które aktualizują interfejs, powodują dodatkowe renderowanie każdej klatki w w którym ma być uruchamiana animacja. Dlatego korzystanie z animacji wymagających dużych ilości zasobów może negatywnie wpłynąć na wydajność aplikacji.
Elementy wymagane do animowania interfejsu użytkownika są dodawane do etapu animacji w: z potokiem renderowania. Możesz się dowiedzieć, czy Twoje animacje wpływają na wydajności aplikacji, włączając Renderowanie GPU w profilu oraz monitorowania etapu animacji. Aby uzyskać więcej informacji, przeczytaj artykuł Profilowanie renderowania GPU .