System animacji obiektów to solidna platforma, która umożliwia animację niemal wszystkiego. Możesz zdefiniować animację, która zmienia dowolną właściwość obiektu w czasie, niezależnie od tego, czy obiekt jest widoczny na ekranie. Animacja właściwości zmienia wartość właściwości (pola w obiekcie) w określonym czasie. Aby coś animować, musisz określić właściwość obiektu, którą chcesz animować, np. jego położenie na ekranie, czas trwania animacji oraz wartości, między którymi chcesz ją wykonać.
System animacji właściwości umożliwia określenie tych właściwości animacji:
- 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 się powtarzać po zakończeniu odtwarzania oraz ile razy ma się powtórzyć. Możesz też określ, czy animacja ma być odtwarzana wstecz. Ustawienie go na odwrotne odtwarzanie powoduje, że animacja jest odtwarzana najpierw do przodu, a potem do tyłu, aż do osiągnięcia liczby powtórzeń.
- Zestawy animacji: możesz grupować animacje w logiczne zestawy, które odtwarzają się razem lub kolejno albo 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 w zależności od ogólnego obciążenia systemu i tego, 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 wyjaśnimy, jak działa animacja, na prostym przykładzie. Rysunek 1 przedstawia hipotetyczny obiekt, który jest animowany za pomocą właściwości x
, która reprezentuje jego położenie poziome na ekranie. Czas trwania animacji wynosi 40 ms, a odległość do przebycia – 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. Oto przykład animacji z interpolacją liniową, czyli obiekt porusza się z niezmienną prędkością.

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.

Rysunek 2. Przykład animacji nieliniowej
Przyjrzyjmy się szczegółowo, jak ważne komponenty systemu animacji właściwości obliczają animacje takie jak te pokazane powyżej. Rysunek 3 przedstawia główne klasy współdziałają ze sobą.

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.
Parametr ValueAnimator
zawiera zasadę TimeInterpolator
, która 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 rysunku 2 wartość TimeInterpolator
to AccelerateDecelerateInterpolator
, a wartość 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
animacji. Gdy zadzwonisz pod numer start()
, rozpocznie się animacja. 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ął. Upływający ułamek reprezentuje odsetek czasu, przez który trwała animacja: 0 oznacza 0%, a 1 to 100%. Na przykład na rysunku 1 ułamek czasu w miejscu t = 10 ms wynosiłby 0,25, ponieważ łączny czas to t = 40 ms.
Gdy funkcja ValueAnimator
zakończy obliczanie ułamka, funkcja
wywołuje aktualnie ustawioną funkcję TimeInterpolator
, aby obliczyć
ułamek interpolowany. Interpolowana iloraz mapuje upływający ułamek na nowy ułamek, który uwzględnia ustawioną interpolację czasu. 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 obiektów View
. Jeśli chcesz animować obiekty inne niż View
, musisz zaimplementować własny kod. System animacji widoku jest też ograniczony tym, że udostępnia tylko kilka aspektów obiektu View
do animowania, takich jak skalowanie i obrót widoku, ale nie kolor tła.
Kolejną wadą systemu animacji widoku jest to, że modyfikował on tylko miejsce, w którym widok został narysowany, a nie sam widok. Jeśli na przykład animujesz przycisk, aby przesuwał się po ekranie, przycisk jest prawidłowo rysowany, ale rzeczywista lokalizacja, w której można go kliknąć, się nie zmienia, więc musisz zaimplementować własną logikę, aby sobie z tym poradzić.
System animacji właściwości całkowicie usuwa te ograniczenia. Możesz animować dowolną właściwość dowolnego obiektu (widoków i niewidocznych) i w ten sposób modyfikować sam obiekt. 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 Twoje wymagania lub jeśli dotychczasowy kod działa już tak, jak chcesz, nie musisz używać systemu animacji w usłudze. W niektórych sytuacjach może też być sensowne użycie obu systemów animacji.
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 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. Te podklasy rozszerzają klasę Animator
:
Tabela 1. Animatorzy
Kategoria | Opis |
---|---|
ValueAnimator |
Główny mechanizm ustawiania czasu animacji właściwości, który oblicza też wartości właściwości, która ma być animowana. Zawiera ona wszystkie podstawowe funkcje, które obliczają wartości animacji i zawierają szczegóły dotyczące czasu trwania każdej animacji, informacje o tym, czy animacja się powtarza, a także możliwość ustawiania typów niestandardowych do oceny. Animacja właściwości składa się z 2 części: obliczenia wartości animowanych i ustawienia tych wartości w obiekcie oraz właściwości, która jest animowana. ValueAnimator nie wykonuje drugiej części, więc musisz nasłuchiwać aktualizacji wartości obliczanych przez ValueAnimator i modyfikować obiekty, które chcesz animować, za pomocą własnej logiki. Więcej informacji znajdziesz w sekcji Animowanie za pomocą 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 |
Udostępnia mechanizm grupowania animacji, aby mogły one działać w zależności od siebie. Możesz ustawić odtwarzanie animacji po kolei, po kolei lub później. określonego opóźnienia. Więcej informacji znajdziesz w sekcji Koordynowanie wielu animacji za pomocą zestawów animatorów. |
Weryfikatorzy informują system animacji właściwości, jak obliczyć wartości danej
usłudze. Wykorzystują one dane dotyczące czasu, które są dostarczane przez klasę Animator
, wartość początkową i końcową animacji oraz na podstawie tych danych obliczają animowane wartości właściwości. System animacji obiektów udostępnia te funkcje oceny:
Tabela 2. Weryfikatorzy
Klasa/interfejs | Opis |
---|---|
IntEvaluator |
Domyślny tester do obliczania wartości właściwości int . |
FloatEvaluator |
Domyślny oceniający do obliczania wartości właściwości float . |
ArgbEvaluator |
Domyślny oceniający do obliczania wartości właściwości kolorów, które są reprezentowane jako wartości szesnastkowe. |
TypeEvaluator |
Interfejs umożliwiający tworzenie własnych oceniaczy. 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 o pisaniu niestandardowego oceniacza znajdziesz w sekcji Korzystanie z TypeEvaluator. |
Interpolator czasowy określa, jak określone wartości w animacji są obliczane jako funkcja czasu. Możesz na przykład określić, że animacje mogą pojawiać się 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 zawiera opis interpolacji zawartych w elementach 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 jest na początku i na końcu powolna, ale przyspiesza w środku. |
AccelerateInterpolator |
Interpolator, którego szybkość zmiany 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 szybkość zmian początkowo jest duża, a potem maleje. |
LinearInterpolator |
Interpolator, którego szybkość zmian jest stała. |
OvershootInterpolator |
Interpolator, którego zmiana przesuwa się do przodu i przestrzeliwuje ostatnią wartość, a potem wraca. |
TimeInterpolator |
Interfejs umożliwiający wdrożenie własnego interpolatora. |
Tworzenie animacji 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 funkcja ValueAnimator
zaczyna obliczać wartości animacji w zakresie od 0 do 100 przez 1000 ms, gdy uruchomiona jest 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 element ValueAnimator
zaczyna obliczać wartości animacji między elementami startPropertyValue
i endPropertyValue
, używając logiki dostarczonej przez MyTypeEvaluator
przez 1000 ms, gdy wykonywana jest metoda start()
.
Aby używać wartości animacji, dodaj do obiektu ValueAnimator
parametr AnimatorUpdateListener
, jak w tym kodzie:
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
Obiekt ObjectAnimator
jest podklasą obiektu ValueAnimator
(omówionego w poprzedniej sekcji) i łączy mechanizm ustalania czasu oraz obliczanie wartości obiektu ValueAnimator
z możliwością animowania nazwanej właściwości obiektu docelowego. Dzięki temu animacja dowolnego obiektu jest znacznie łatwiejsza, ponieważ nie musisz już implementować ValueAnimator.AnimatorUpdateListener
, ponieważ animowana właściwość 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 usługi ObjectAnimator
były prawidłowo aktualizowane, musisz:
- 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ć możliwość dostępu do tej właściwości za pomocą tej metody ustawiania. 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 do klasy metodę settera, jeśli masz do tego odpowiednie 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.
- Zamiast tego użyj
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 gettera musi mieć postaćget<PropertyName>()
. Jeśli na przykład nazwa właściwości tofoo
, musisz mieć metodęgetFoo()
. - Metody getter (jeśli są potrzebne) i setter właściwości, którą animujesz, muszą działać na tym samym typie co wartości początkowa i końcowa, które podajesz 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 tego, jaką właściwość lub jaki obiekt animujesz, możesz potrzebować wywołania metody
invalidate()
w widoku, aby wymusić ponowne narysowanie ekranu z aktualizowanymi wartościami animacji. 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 metody właściwości w widoku, np.setAlpha()
isetTranslationX()
, powodują nieważność widoku, więc nie musisz go unieważniać, gdy wywołujesz te metody z nowymi wartościami. Więcej informacji o słuchaczach znajdziesz w sekcji Detektory animacji.
Choreografia wielu animacji za pomocą zestawu animatorów
W wielu przypadkach chcesz odtwarzać animację w zależności od tego, kiedy rozpoczyna się lub kończy inna animacja. System Android umożliwia grupowanie animacji w jedną AnimatorSet
, dzięki czemu możesz określić, czy animacje mają być uruchamiane jednocześnie, sekwencyjnie czy po określonym opóźnieniu. Obiekty AnimatorSet
możesz też zagnieżdżać wewnątrz siebie.
Ten fragment kodu odtwarza Animator
w następujący sposób:
- Odtwarzam
bounceAnim
. - Odtwarza:
squashAnim1
,squashAnim2
,stretchAnim1
istretchAnim2
. - Odtwarzam
bounceBackAnim
. - Odtwarza
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
Podczas trwania animacji możesz słuchać ważnych zdarzeń za pomocą opisanych poniżej obiektów nasłuchujących.
Animator.AnimatorListener
onAnimationStart()
– wywoływane po rozpoczęciu animacji.onAnimationEnd()
– wywoływane, gdy animacja się zakończy.onAnimationRepeat()
– wywoływana, gdy animacja się powtarza.onAnimationCancel()
– wywoływana, gdy animacja zostanie anulowana. Anulowana animacja wywołuje równieżonAnimationEnd()
, niezależnie od tego, jak została zakończona.
ValueAnimator.AnimatorUpdateListener
-
onAnimationUpdate()
– wywoływane przy każdej klatce animacji. Odsłuchuj to zdarzenie, aby używać wartości obliczanych przezValueAnimator
podczas animacji. Aby użyć tej wartości, wyślij zapytanie do obiektuValueAnimator
przekazywane do zdarzenia, by uzyskać bieżącą animowaną wartość za pomocą metodygetAnimatedValue()
. Jeśli używaszValueAnimator
, musisz zaimplementować ten listener.W zależności od tego, jaką właściwość lub jaki obiekt animujesz, możesz potrzebować wywołania funkcji
invalidate()
w przypadku widoku, aby wymusić ponowne narysowanie tego obszaru ekranu z nowymi wartościami animacji. Na przykład animowanie właściwości koloru obiektu rysowanego powoduje aktualizację ekranu tylko wtedy, gdy obiekt ponownie się rysuje. Wszystkie metody właściwości w klasie View, takie jaksetAlpha()
isetTranslationX()
, powodują nieważność obiektu View, więc nie musisz anulować jego ważności, gdy wywołujesz te metody z nowymi wartościami.
-
Jeśli nie chcesz implementować wszystkich metod interfejsu Animator.AnimatorListener
, możesz rozszerzyć klasę AnimatorListenerAdapter
zamiast implementować interfejs Animator.AnimatorListener
. Klasa AnimatorListenerAdapter
zawiera puste
implementacji metod, które można zastąpić.
Na przykład ten fragment kodu tworzy obiekt AnimatorListenerAdapter
tylko do wywołania zwrotnego onAnimationEnd()
:
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()); }
Animowanie zmian układu obiektów ViewGroup
System animacji właściwości umożliwia animowanie zmian w obiektach ViewGroup, a także łatwe animowanie samych obiektów View.
Zmiany układu w grupie widoków możesz animować za pomocą klasy LayoutTransition
. Widoki w grupie widoków
mogą pojawiać się i znikać.
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 w przypadku elementów wyświetlanych 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 uruchamiana w przypadku elementów znikających z kontenera.CHANGE_DISAPPEARING
– flaga wskazująca animację, która działa na elementach zmieniających się z powodu zniknięcia elementu z kontenera.
Możesz zdefiniować własne animacje niestandardowe dla tych 4 typów zdarzeń, aby dostosować wygląd przejść układu, lub po prostu wskazać systemowi animacji, aby 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 tego atrybutu na wartość true powoduje automatyczne animowanie widoków dodanych lub usuniętych z grupy widoków, a także pozostałych widoków w tej grupie.
Animowanie zmian stanu widoku za pomocą klasy StateListAnimator
Klasa StateListAnimator
umożliwia definiowanie animatorów, które działają, gdy zmienia się stan widoku. 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
element <selector>
i podrzędne elementy <item>
określone przez każdy z nich
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, gdy zmienia się stan tego przycisku, używane są animacje zdefiniowane w elementach animate_scale.xml
.
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żywanie funkcji TypeEvaluator
Jeśli chcesz animować typ nieznany systemowi Android, możesz utworzyć własny evaluator, implementując interfejs 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. Interpolowana iloraz jest tym, co TypeEvaluator
otrzymuje za pomocą parametru fraction
, więc podczas obliczania wartości animowanych nie musisz uwzględniać interpolatora.
Używanie interpolacji
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 animatorów, który reprezentuje upływ czasu animacji. Interpolator modyfikuje ten ułamek, aby zbiegł się z typem
i animację. System Android udostępnia zestaw popularnych interpolatorów,
android.view.animation package
. Jeśli żaden z nich nie odpowiada Twoim potrzebom, możesz wdrożyć interfejs TimeInterpolator
i utworzyć własny.
Poniżej porównujemy sposób obliczania interpolowanych ułamków przez domyślny interpolator AccelerateDecelerateInterpolator
i interpolator LinearInterpolator
.
LinearInterpolator
nie ma wpływu na ułamek czasu, który upłynął. AccelerateDecelerateInterpolator
przyspiesza w ramach animacji i zwalnia na jej końcu. Te metody definiują logikę tych interpolacji:
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; }
LinearInterpolator
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) | Interpolowana cześć (przyspieszanie/zwalnianie) |
---|---|---|
0 | 0 | 0 |
200 | .2 | 0,1 |
400 | 0,4 | 0,345 |
600 | 0,6 | 0,654 |
800 | 0,8 | .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. W okresie od 200 do 600 ms model AccelerateDecelerateInterpolator
zmienia wartości szybciej niż model LinearInterpolator
, a w okresie od 600 do 1000 ms – wolniej.
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łasny interpolator, który kontroluje zachowanie animacji w interwale między czasem poprzedniej klatek kluczowej a czasem tej klatek.
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
. Gdy już go masz, możesz uzyskać animatora, przekazując obiekt PropertyValuesHolder
i obiekt do animowania. Jak to zrobić, pokazuje poniższy fragment kodu:
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. System animacji widoku przekształcił obiekty widoku, 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. prowadziło to do takich zachowań jak obiekt nadal znajdujący się w pierwotnej lokalizacji, mimo że został narysowany 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 kontrolują skalowanie 2D widoku wokół punktu obrotu.pivotX
ipivotY
: te właściwości określają położenie osi obrotu, wokół której zachodzą transformacje obrotu i skalowania. Domyślnie okrąg znajduje się na środku obiektu.x
iy
: to proste właściwości pomocnicze opisujące ostateczne położenie widoku w kontenerze jako suma wartości lewej i górnej oraz wartości przesunięcia X i Y.alpha
: reprezentuje przezroczystość w wersji alfa w widoku danych. Domyślnie ma ona wartość 1 (nieprzezroczysta), a wartość 0 oznacza pełną przezroczystość (niewidoczna).
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 o tworzeniu animatorów znajdziesz w sekcjach poświęconych animacji za pomocą komponentów ValueAnimator i ObjectAnimator.
Tworzenie animacji za pomocą ViewPropertyAnimator
Element ViewPropertyAnimator
zapewnia prosty sposób na animowanie kilku właściwości obiektu View
równolegle za pomocą jednego obiektu bazowego Animator
. 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 kod używany do wywoływania funkcji ViewPropertyAnimator
jest znacznie bardziej zwięzły i łatwiejszy do odczytania. 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 obiektu umożliwia deklarowanie animacji obiektu za pomocą kodu XML zamiast programowo. Definiując animacje w pliku XML, możesz je łatwo używać w różnych działaniach 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>
Aby znaleźć atrybuty, których możesz używać w deklaracji XML, zapoznaj się z zasobami dotyczącymi animacji. W tym przykładzie 2 zestawy animacji obiektów są odtwarzane kolejno, a pierwszy zagnieżdżony zestaw odtwarza 2 animacje obiektów razem:
<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 wczytać zasoby XML w kodzie do obiektu AnimatorSet
, a potem przed uruchomieniem zestawu animacji ustawić obiekty docelowe dla wszystkich 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();
Możesz też zadeklarować ValueAnimator
w pliku XML, jak 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ć w kodzie poprzedniej wartości ValueAnimator
, musisz zainicjować obiekt, dodać element AnimatorUpdateListener
, uzyskać zaktualizowaną wartość animacji i użyć jej we właściwości jednej z widoków, jak pokazano 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. Aby sprawdzić, czy animacje wpływają na wydajność aplikacji, włącz Profilowanie renderowania GPU i obserwuj etap animacji. Więcej informacji znajdziesz w przewodniku po profilowaniu renderowania GPU.