Das Property-Animationssystem ist ein robustes Framework, mit dem Sie fast alles animieren können. Sie können eine Animation definieren, um Objekteigenschaften im Laufe der Zeit zu ändern, unabhängig davon, ob sie auf dem Bildschirm erscheint oder nicht. Bei einer Property-Animation ändert sich der Wert einer Property (eines Felds in einem Objekt) über einen bestimmten Zeitraum. Wenn Sie etwas animieren möchten, geben Sie die Objekteigenschaft an, die Sie animieren möchten, z. B. die Position eines Objekts auf dem Bildschirm, die Dauer der Animation und die Werte, zwischen denen die Animation erfolgen soll.
Mit dem Property-Animationssystem können Sie die folgenden Eigenschaften einer Animation definieren:
- Dauer: Sie können die Dauer einer Animation angeben. Die Standardlänge beträgt 300 ms.
- Zeitinterpolation: Sie können angeben, wie die Werte für die Eigenschaft berechnet werden, der aktuell verstrichenen Zeit der Animation.
- Wiederholungsanzahl und -verhalten: Sie können angeben, ob eine Animation wiederholt werden soll, wenn das Ende einer Dauer erreicht und wie oft die Animation wiederholt werden soll. Sie können auch angeben, ob die Animation rückwärts wiedergegeben werden soll. Umgekehrte Wiedergaben festlegen wird die Animation wiederholt vor- und zurückgespult, bis die gewünschte Anzahl an Wiederholungen erreicht ist.
- Animator-Sets: Sie können Animationen in logische Sets gruppieren, die gleichzeitig, nacheinander oder nach bestimmten Verzögerungen abgespielt werden.
- Verzögerung bei Frame-Aktualisierung: Sie können angeben, wie oft die Frames der Animation aktualisiert werden sollen. Standardmäßig wird alle 10 ms aktualisiert. Die Geschwindigkeit, mit der Ihre Anwendung Frames aktualisieren kann, hängt jedoch letztendlich davon ab, wie ausgelastet das System insgesamt ist und wie schnell das System den zugrunde liegenden Timer bedienen kann.
Ein vollständiges Beispiel für die Eigenschaftenanimation finden Sie in der Klasse ChangeColor
im Beispiel CustomTransition auf GitHub.
Funktionsweise von Property-Animationen
Sehen wir uns zuerst anhand eines einfachen Beispiels an, wie eine Animation funktioniert. Abbildung 1 zeigt eine
hypothetisches Objekt, das mit seiner x
-Eigenschaft animiert ist, die seine
horizontalen Position auf einem Bildschirm. Die Dauer der Animation ist auf 40 ms und die Entfernung
40 Pixel beträgt. Alle 10 ms (Standard-Frame-Aktualisierungsrate) wird das Objekt verschoben.
horizontal x 10 Pixel. Nach 40 ms stoppt die Animation und das Objekt endet bei
horizontale Position 40. Dies ist ein Beispiel für eine Animation mit linearer Interpolation. Das Objekt bewegt sich also mit konstanter Geschwindigkeit.
Sie können Animationen auch so definieren, dass sie eine nicht lineare Interpolation haben. Abbildung 2 zeigt ein hypothetisches Objekt, das zu Beginn der Animation beschleunigt und am Ende der Animation wieder verlangsamt. Das Objekt bewegt sich in 40 ms immer noch um 40 Pixel, aber nicht linear. Im am Anfang, wird diese Animation bis zur Hälfte beschleunigt und dann bis zum Ende der Animation. Wie Abbildung 2 zeigt, ist die zurückgelegte Strecke am Anfang und am Ende der Animation ist kleiner als in der Mitte.
Sehen wir uns genauer an, wie die wichtigen Komponenten des Animationen wie die oben dargestellten berechnet. Abbildung 3 zeigt, wie die Hauptklassen miteinander zusammenarbeiten.
Das ValueAnimator
-Objekt verfolgt das Timing Ihrer Animation.
z. B. wie lange die Animation läuft, und der aktuelle Wert der Eigenschaft,
zu animieren.
ValueAnimator
kapselt ein TimeInterpolator
, das die Animationsinterpolation definiert, und ein TypeEvaluator
, das festlegt, wie Werte für die zu berechnende Eigenschaft berechnet werden.
animiert. In Abbildung 2 wäre AccelerateDecelerateInterpolator
beispielsweise TimeInterpolator
und IntEvaluator
TypeEvaluator
.
Um eine Animation zu starten, erstellen Sie ein ValueAnimator
mit dem
für die Property, die Sie animieren möchten, sowie die Start- und Endwerte
der Animation. Wenn Sie start()
aufrufen, wird die Animation
beginnt. Während der gesamten Animation berechnet ValueAnimator
einen verstrichenen Bruchteil zwischen 0 und 1, basierend auf der Dauer der Animation und der verstrichenen Zeit. Der verstrichene Bruchteil gibt den Prozentsatz der Zeit an, der seit Beginn der Animation vergangen ist. „0“ steht für 0 % und „1“ für 100 %. In Abbildung 1 würde der verstrichene Anteil bei t = 10 ms beispielsweise 0,25 betragen, da die Gesamtdauer t = 40 ms beträgt.
Wenn die ValueAnimator
die Berechnung eines verstrichenen Bruchteils abgeschlossen hat, ruft sie die aktuell festgelegte TimeInterpolator
auf, um einen interpolierten Bruchteil zu berechnen. Ein interpolierter Bruch ordnet den verstrichenen Teil einem neuen
Bruch, der die festgelegte Zeitinterpolation berücksichtigt. In Abbildung 2 ist beispielsweise
da die Animation langsam beschleunigt wird, ist der interpolierte Bruch von etwa 0,15 kleiner als der Wert
verstrichener Bruchteil, 0,25, bei t = 10 ms. In Abbildung 1 ist der interpolierte Bruch immer gleich
der verstrichene Teil.
Wenn der interpolierte Bruch berechnet wird, ruft ValueAnimator
auf
das entsprechende TypeEvaluator
, um den Wert des
basierend auf dem interpolierten Bruch, dem Startwert und der Eigenschaft
Endwert der Animation. In Abbildung 2 betrug der interpolierte Bruchteil bei t = 10 ms beispielsweise 0,15. Der Wert für die Property zu diesem Zeitpunkt wäre also 0,15 × (40 − 0) oder 6.
Unterschied zwischen Attribut- und Datenansichtsanimation
Das Ansichtsanimationssystem bietet die Möglichkeit, nur View
zu animieren.
Objekte. Wenn Sie also Nicht-View
-Objekte animieren möchten, müssen Sie
eigenen Code erstellen. Das Ansichtsanimationssystem ist außerdem dadurch eingeschränkt, dass es nur
einige Aspekte eines View
-Objekts zum Animieren bereithält, z. B. die Skalierung und
beispielsweise die Rotation einer Ansicht, aber nicht die Hintergrundfarbe.
Ein weiterer Nachteil des Systems zur Ansichtsanimation ist, dass nur die Position geändert wurde, an der die Ansicht gezeichnet wurde, nicht aber die Ansicht selbst. Wenn Sie beispielsweise eine Schaltfläche zum Verschieben über den Bildschirm ziehen, wird die Schaltfläche korrekt gezeichnet, aber an der tatsächlichen Position, an der Sie auf das Symbol ändert sich nichts, Sie müssen also Ihre eigene Logik dafür implementieren.
Mit dem Eigenschaftsanimationssystem werden diese Einschränkungen vollständig entfernt, und Sie können Jede Eigenschaft eines beliebigen Objekts (Views und Nicht-Views) und das Objekt selbst wird tatsächlich geändert. Das Eigenschaftsanimationssystem ist außerdem robuster in der Art und Weise, wie es Animationen durchführt. Bei weisen Sie den zu animierenden Eigenschaften wie Farbe, Position oder Größe und können Aspekte der Animation definieren, z. B. Interpolation und Synchronisierung mehrerer Animatoren.
Das Ansichtsanimationssystem nimmt jedoch weniger Zeit für die Einrichtung in Anspruch und erfordert weniger Code zum Schreiben. Wenn die Ansichtsanimation alles erledigt, was Sie tun möchten, oder wenn Ihr vorhandener Code bereits wie gewünscht funktioniert, müssen Sie das Property-Animationssystem nicht verwenden. Es kann auch sinnvoll sein, beide Animationssysteme für unterschiedliche Situationen zu verwenden, wenn der Anwendungsfall dies erfordert.
API-Übersicht
Die meisten APIs des Property-Animationssystems finden Sie unter android.animation
. Da das Ansichtsanimationssystem bereits viele Interpolatoren in android.view.animation
definiert, können Sie diese Interpolatoren auch im Property-Animationssystem verwenden. In den folgenden Tabellen werden die Hauptkomponenten des Property-Animationssystems beschrieben.
Die Klasse Animator
bietet die grundlegende Struktur zum Erstellen von Animationen. Normalerweise verwenden Sie diese Klasse nicht direkt, da sie nur minimale
Funktionen, die erweitert werden müssen, um Animationswerte vollständig zu unterstützen. Die folgenden
abgeleiteten Klassen erweitern Animator
:
Klasse | Beschreibung |
---|---|
ValueAnimator |
Die Haupt-Timing-Engine für die Property-Animation, die auch die Werte für die zu animierende Property berechnet. Sie verfügt über alle Hauptfunktionen zum Berechnen von Animationen
und enthält die Timing-Details jeder Animation, Informationen darüber, ob ein
Animationswiederholungen, Listener, die Update-Ereignisse empfangen, und die Möglichkeit, benutzerdefinierte
die auszuwerten sind. Die Animation von Properties besteht aus zwei Schritten: dem Berechnen der animierten Werte und dem Festlegen dieser Werte für das Objekt und die Property, die animiert werden soll. Das zweite Stück wird in ValueAnimator nicht ausgeführt, du musst also zuhören
für Aktualisierungen von Werten, die von ValueAnimator berechnet wurden und
modifizieren Sie die Objekte, die Sie mit Ihrer eigenen Logik animieren möchten. Weitere Informationen finden Sie im Abschnitt Mit ValueAnimator animieren. |
ObjectAnimator |
Eine Unterklasse von ValueAnimator , mit der Sie ein Zielobjekt und eine Objekteigenschaft festlegen können, die animiert werden soll. Diese Klasse aktualisiert die Property entsprechend, wenn ein neuer Wert für die Animation berechnet wird. Sie möchten
in den meisten Fällen ObjectAnimator ,
da dies die Animation von Werten für Zielobjekte erheblich vereinfacht. Manchmal möchten Sie ValueAnimator jedoch direkt verwenden, da ObjectAnimator einige weitere Einschränkungen hat, z. B. dass bestimmte Zugriffsmethoden auf dem Zielobjekt vorhanden sein müssen. |
AnimatorSet |
Bietet einen Mechanismus zum Gruppieren von Animationen, sodass sie in in Beziehung zueinander stehen. Sie können Animationen so festlegen, dass sie zusammen, hintereinander oder danach wiedergegeben werden einer bestimmten Verzögerung. Weitere Informationen finden Sie im Abschnitt Mehrere Animationen mit Animator-Sets choreographieren. |
Mithilfe von Evaluatoren wird dem Property-Animationssystem mitgeteilt, wie Werte für eine bestimmte Property berechnet werden sollen. Sie verwenden die Timing-Daten, die von einer Animator
-Klasse bereitgestellt werden, sowie den Start- und Endwert der Animation und berechnen anhand dieser Daten die animierten Werte der Property. Im Animationssystem für Unterkünfte stehen die folgenden Bewerter zur Verfügung:
Klasse/Benutzeroberfläche | Beschreibung |
---|---|
IntEvaluator |
Der Standardbewerter zum Berechnen von Werten für int -Properties. |
FloatEvaluator |
Der Standard-Evaluator zur Berechnung von Werten für float -Properties. |
ArgbEvaluator |
Der Standard-Evaluator zur Berechnung von Werten für dargestellte Farbeigenschaften als Hexadezimalwerte. |
TypeEvaluator |
Eine Benutzeroberfläche, mit der Sie Ihre eigenen Bewertungstools erstellen können. Wenn Sie eine Objekteigenschaft animieren, die keine int -, float - oder Farbeigenschaft ist, müssen Sie die TypeEvaluator -Schnittstelle implementieren, um anzugeben, wie die animierten Werte der Objekteigenschaft berechnet werden sollen. Sie können auch eine benutzerdefinierte TypeEvaluator für int , float und Farbwerte angeben, wenn Sie diese Typen anders als das Standardverhalten verarbeiten möchten.
Weitere Informationen finden Sie im Abschnitt TypeEvaluator verwenden.
Informationen zur Entwicklung eines benutzerdefinierten Evaluators. |
Mit einem Zeitinterpolator wird definiert, wie bestimmte Werte in einer Animation als Funktion der Zeit berechnet werden. Sie können beispielsweise festlegen, dass Animationen linear ablaufen, d. h., dass sich die Animation die ganze Zeit gleichmäßig bewegt. Sie können auch festlegen, dass Animationen nicht linear ablaufen, z. B. dass sie am Anfang beschleunigen und am Ende der Animation verlangsamen. In Tabelle 3 werden die Interpolatoren beschrieben, die in android.view.animation
enthalten sind. Wenn keiner der bereitgestellten Interpolatoren Ihren Anforderungen entspricht, implementieren Sie die TimeInterpolator
-Schnittstelle und erstellen Sie Ihre eigene. Weitere Informationen zum Schreiben eines benutzerdefinierten Elements finden Sie unter Interpolatoren verwenden.
Interpolator.
Klasse/Schnittstelle | Beschreibung |
---|---|
AccelerateDecelerateInterpolator |
Interpolator, dessen Änderungsrate langsam beginnt und endet, aber beschleunigt wird durch die Mitte gehen. |
AccelerateInterpolator |
Interpolator, deren Änderungsrate langsam beginnt, beschleunigt. |
AnticipateInterpolator |
Interpolator, dessen Änderung rückwärts beginnt und dann nach vorne geschoben wird. |
AnticipateOvershootInterpolator |
Ein Interpolator, dessen Änderung rückwärts beginnt, nach vorne springt und den Zielwert überspringt, um dann schließlich zum Endwert zurückzukehren. |
BounceInterpolator |
Ein Interpolator, dessen Änderung am Ende abprallt. |
CycleInterpolator |
Ein Interpolator, dessen Animation für eine bestimmte Anzahl von Zyklen wiederholt wird. |
DecelerateInterpolator |
Interpolatoren, deren Änderungsrate schnell beginnt, langsamer wird. |
LinearInterpolator |
Ein Interpolator, dessen Änderungsrate konstant ist. |
OvershootInterpolator |
Ein Interpolator, dessen Änderung nach vorne springt und den letzten Wert überspringt, bevor er wieder zurückkommt. |
TimeInterpolator |
Eine Schnittstelle, mit der Sie Ihren eigenen Interpolator implementieren können. |
Animationen mit ValueAnimator
Mit der ValueAnimator
-Klasse können Sie Werte eines bestimmten Typs während der Dauer einer Animation animieren, indem Sie eine Reihe von int
-, float
- oder Farbwerten angeben, die animiert werden sollen. Sie erhalten ein ValueAnimator
, indem Sie eine der
seine Factory-Methoden: ofInt()
, ofFloat()
oder ofObject()
. Beispiel:
Kotlin
ValueAnimator.ofFloat(0f, 100f).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f); animation.setDuration(1000); animation.start();
In diesem Code beginnt ValueAnimator
, die Werte der Animation zwischen 0 und 100 für eine Dauer von 1.000 ms zu berechnen, wenn die Methode start()
ausgeführt wird.
Sie können auch einen benutzerdefinierten Typ für die Animation angeben. Gehen Sie dazu so vor:
Kotlin
ValueAnimator.ofObject(MyTypeEvaluator(), startPropertyValue, endPropertyValue).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue); animation.setDuration(1000); animation.start();
In diesem Code beginnt ValueAnimator
, die Werte der Animation zwischen startPropertyValue
und endPropertyValue
mithilfe der Logik von MyTypeEvaluator
für eine Dauer von 1.000 ms zu berechnen, wenn die Methode start()
ausgeführt wird.
Sie können die Werte der Animation verwenden, indem Sie dem ValueAnimator
-Objekt ein AnimatorUpdateListener
hinzufügen, wie im folgenden Code gezeigt:
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); } });
Im onAnimationUpdate()
können Sie auf den aktualisierten Animationswert zugreifen und ihn in der Eigenschaft
eine Ihrer Ansichten. Weitere Informationen zu Listenern finden Sie im Abschnitt Animation Listeners.
Mit ObjectAnimator animieren
ObjectAnimator
ist eine abgeleitete Klasse von ValueAnimator
(wie im vorherigen Abschnitt besprochen) und kombiniert die zeitliche Abfolge
Berechnung von ValueAnimator
mit der Möglichkeit,
Benannte Eigenschaft eines Zielobjekts animieren Das erleichtert die Animation von Objekten erheblich, da Sie die ValueAnimator.AnimatorUpdateListener
nicht mehr implementieren müssen, da die animierte Eigenschaft automatisch aktualisiert wird.
Das Instanziieren eines ObjectAnimator
ähnelt einem ValueAnimator
, Sie geben jedoch zusätzlich das Objekt und den Namen der Eigenschaft dieses Objekts (als
einen String) zusammen mit den Werten, zwischen denen animiert werden soll:
Kotlin
ObjectAnimator.ofFloat(textView, "translationX", 100f).apply { duration = 1000 start() }
Java
ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f); animation.setDuration(1000); animation.start();
Damit die ObjectAnimator
-Attribute aktualisiert werden
müssen Sie Folgendes tun:
- Die zu animierende Objekteigenschaft muss eine Setzerfunktion (in CamelCase) vom Typ
set<PropertyName>()
haben. Da dieObjectAnimator
wird die Property während der Animation automatisch aktualisiert, muss aber weiterhin auf die Property zugreifen können. mit dieser Setter-Methode. Lautet der Name der Property beispielsweisefoo
, müssen Sie haben einesetFoo()
-Methode. Wenn diese Setter-Methode nicht existiert, gibt es drei Optionen:- Fügen Sie der Klasse die Setter-Methode hinzu, wenn Sie über die entsprechenden Rechte verfügen.
- Verwenden Sie eine Wrapper-Klasse, für die Sie die Berechtigung zum Ändern haben, und lassen Sie diesen Wrapper den Wert mit einer gültigen Setzermethode empfangen und an das ursprüngliche Objekt weiterleiten.
- Verwenden Sie stattdessen
ValueAnimator
.
- Wenn Sie nur einen Wert für den Parameter
values...
in einer derObjectAnimator
-Factory-Methoden angeben, wird davon ausgegangen, dass es sich um den Endwert des Animation. Daher muss die Objekteigenschaft, die Sie animieren, eine Getter-Funktion haben. das den Startwert der Animation ermittelt. Die Getter-Funktion muss das Formatget<PropertyName>()
haben. Wenn der Property-Name beispielsweisefoo
lautet, benötigen Sie die MethodegetFoo()
. - Die Getter- (falls erforderlich) und Setter-Methoden der animierten Eigenschaft müssen denselben Typ haben wie die Start- und Endwerte, die Sie für
ObjectAnimator
angeben. Beispiel: Sie benötigentargetObject.setPropName(float)
undtargetObject.getPropName()
, wenn Sie die folgendeObjectAnimator
erstellen:ObjectAnimator.ofFloat(targetObject, "propName", 1f)
- Je nachdem, welches Attribut oder Objekt Sie animieren, müssen Sie möglicherweise die Methode
invalidate()
für eine Ansicht aufrufen, um den Bildschirm mit den aktualisierten animierten Werten neu zu zeichnen. Sie tun dies in deronAnimationUpdate()
Callback des Nutzers an. Wenn Sie beispielsweise die Farbeigenschaft eines Drawable-Objekts animieren, werden nur dann Änderungen auf dem Bildschirm vorgenommen, wenn sich das Objekt neu zeichnet. Alle Property-Setter für die Datenansicht, z. B.setAlpha()
undsetTranslationX()
, machen die Datenansicht ordnungsgemäß ungültig. Sie müssen sie also nicht ungültig machen, wenn Sie diese Methoden mit neuen Werten aufrufen. Weitere Informationen zu Listenern finden Sie im Abschnitt Animations-Listener:
Mit einem AnimatorSet mehrere Animationen choreografieren
Häufig möchten Sie eine Animation abspielen,
die davon abhängt, wann eine andere Animation beginnt
beendet. Mit dem Android-System können Sie Animationen in einer AnimatorSet
zusammenfassen und angeben, ob sie gleichzeitig, nacheinander oder nach einer bestimmten Verzögerung gestartet werden sollen. Sie können AnimatorSet
-Objekte auch verschachteln.
Im folgenden Code-Snippet werden die folgenden Animator
-Objekte auf folgende Weise wiedergegeben:
bounceAnim
wird abgespielt.squashAnim1
,squashAnim2
,stretchAnim1
undstretchAnim2
.- Klingelt in
bounceBackAnim
. - Klingelt in
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();
Animations-Listener
Mit den unten beschriebenen Listenern können Sie während der Dauer einer Animation auf wichtige Ereignisse warten.
Animator.AnimatorListener
onAnimationStart()
- Wird beim Start der Animation aufgerufen.onAnimationEnd()
– Wird aufgerufen, wenn die Animation endet.onAnimationRepeat()
: Wird aufgerufen, wenn sich die Animation wiederholt.onAnimationCancel()
: Wird aufgerufen, wenn die Animation abgebrochen wird. Eine abgebrochene Animation ruft auchonAnimationEnd()
an, unabhängig davon, wie sie beendet wurden.
ValueAnimator.AnimatorUpdateListener
-
onAnimationUpdate()
wird bei jedem Frame der Animation aufgerufen. Dieses Ereignis überwachen, um die vonValueAnimator
während eines Animation. Wenn du den Wert verwenden möchtest, musst du dasValueAnimator
-Objekt abfragen, das an das Ereignis übergeben wurde, um den aktuellen animierten Wert mit der MethodegetAnimatedValue()
abzurufen. Die Implementierung dieser Listener ist erforderlich, wenn SieValueAnimator
verwenden.Je nachdem, welche Eigenschaft oder welches Objekt Sie animieren, müssen Sie möglicherweise
invalidate()
auf eine Ansicht anwenden, um diesen Bereich des Bildschirms mit den neuen animierten Werten neu zu zeichnen. Wenn Sie beispielsweise die Farbeigenschaft eines Drawable-Objekts animieren, werden nur dann Änderungen auf dem Bildschirm vorgenommen, wenn sich das Objekt neu zeichnet. Alle Property-Setter in View, z. B.setAlpha()
undsetTranslationX()
macht die Ansicht ungültig Die Ansicht muss also nicht ungültig werden, wenn diese Methoden mit neuen Werten aufgerufen werden.
-
Sie können die Klasse AnimatorListenerAdapter
erweitern statt
Implementieren der Animator.AnimatorListener
-Schnittstelle, wenn Sie
alle Methoden des Animator.AnimatorListener
implementieren möchten,
. Die Klasse AnimatorListenerAdapter
stellt leere
Implementierungen der Methoden,
die überschrieben werden können.
Im folgenden Code-Snippet wird beispielsweise ein AnimatorListenerAdapter
nur für den onAnimationEnd()
-Callback erstellt:
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()); }
Layoutänderungen an ViewGroup-Objekten animieren
Das Property-Animationssystem bietet die Möglichkeit, Änderungen an ViewGroup-Objekten zu animieren und View-Objekte selbst ganz einfach zu animieren.
Mit der Klasse LayoutTransition
können Sie Layoutänderungen innerhalb einer ViewGroup animieren. Ansichten in einer ViewGroup können
eine eingeblendete und eine ausgeblendete Animation, wenn Sie sie
aus einer ViewGroup entfernen oder die
Methode setVisibility()
mit
VISIBLE
, INVISIBLE
oder
GONE
. Die verbleibenden Datenansichten in der ViewGroup können auch
wenn Sie Ansichten hinzufügen oder entfernen. Sie können die folgenden Animationen in einem LayoutTransition
-Objekt definieren, indem Sie setAnimator()
aufrufen und ein Animator
-Objekt mit einer der folgenden LayoutTransition
-Konstanten übergeben:
APPEARING
: Diese Markierung gibt die Animation an, die für Elemente ausgeführt wird, die im Container angezeigt werden.CHANGE_APPEARING
: Ein Flag, das die Animation angibt, die für Elemente ausgeführt wird, die sich ändern, weil ein neues Element im Container angezeigt wird.DISAPPEARING
: Diese Markierung gibt die Animation an, die für Elemente ausgeführt wird, wenn sie aus dem Container verschwinden.CHANGE_DISAPPEARING
: ein Flag, das die Animation angibt, die für Elemente ausgeführt wird, die die sich ändern, weil ein Element aus dem Container verschwindet.
Sie können Ihre eigenen benutzerdefinierten Animationen für diese vier Ereignistypen definieren, um das Aussehen anzupassen. Ihrer Layoutübergänge oder weisen Sie das Animationssystem einfach an, die Standardanimationen zu verwenden.
So legen Sie das Attribut android:animateLayoutchanges
für die ViewGroup auf true
fest:
<LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/verticalContainer" android:animateLayoutChanges="true" />
Wenn Sie dieses Attribut auf „wahr“ setzen, werden Ansichten, die der ViewGroup hinzugefügt oder daraus entfernt werden, sowie die verbleibenden Ansichten in der ViewGroup automatisch animiert.
Änderungen des Ansichtsstatus mit StateListAnimator animieren
Mit der Klasse StateListAnimator
können Sie Animatoren definieren, die ausgeführt werden, wenn
ändert sich der Status einer Ansicht. Dieses Objekt dient als Wrapper für ein Animator
-Objekt und ruft diese Animation auf, wenn sich der angegebene Ansichtsstatus (z. B. „gedrückt“ oder „im Fokus“) ändert.
Das StateListAnimator
kann in einer XML-Ressource mit einem Stamm definiert werden
<selector>
-Element und untergeordnete <item>
-Elemente, die jeweils
einen anderen Ansichtsstatus, der durch die Klasse StateListAnimator
definiert wird. Jedes
<item>
enthält die Definition für einen Eigenschaftsanimationssatz.
In der folgenden Datei wird beispielsweise ein Statuslisten-Animator erstellt, der die X- und Y-Skalierung der Ansicht ändert, wenn sie gedrückt wird:
<?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>
Fügen Sie zum Anhängen des Animator für Bundesstaatenlisten an eine Ansicht den Parameter
android:stateListAnimator
so:
<Button android:stateListAnimator="@xml/animate_scale" ... />
Nun werden die in animate_scale.xml
definierten Animationen verwendet, wenn die
Statusänderungen.
Wenn Sie stattdessen einer Ansicht in Ihrem Code einen Animator für Statuslisten zuweisen möchten, verwenden Sie die Methode
AnimatorInflater.loadStateListAnimator()
-Methode und weisen Sie den Animationskünstler der
Ihre Ansicht mit der View.setStateListAnimator()
-Methode.
Statt die Eigenschaften der Ansicht zu animieren, können Sie auch eine Drawable-Animation zwischen
Statusänderungen mithilfe von AnimatedStateListDrawable
.
Einige der System-Widgets in Android 5.0 verwenden diese Animationen standardmäßig. Das folgende Beispiel zeigt,
, um eine AnimatedStateListDrawable
als XML-Ressource zu definieren:
<!-- 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>
TypeEvaluator verwenden
Wenn Sie einen Typ animieren möchten, der dem Android-System unbekannt ist, können Sie einen eigenen Evaluator erstellen, indem Sie die TypeEvaluator
-Schnittstelle implementieren. Die vom Android-System bekannten Typen sind int
, float
oder eine Farbe. Sie werden von den Typbewertern IntEvaluator
, FloatEvaluator
und ArgbEvaluator
unterstützt.
Es gibt nur eine Methode, die im TypeEvaluator
implementiert werden kann.
die Methode evaluate()
. So kann der von Ihnen verwendete Animator an der aktuellen Stelle der Animation einen geeigneten Wert für die animierte Property zurückgeben. Die Klasse FloatEvaluator
zeigt,
Vorgehensweise:
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); } }
Hinweis: Wenn ValueAnimator
(oder ObjectAnimator
) ausgeführt wird, wird ein aktueller verstrichener Bruchteil der Animation (ein Wert zwischen 0 und 1) berechnet und dann eine interpolierte Version davon berechnet, je nachdem, welchen Interpolator Sie verwenden. Der interpolierte Bruchteil wird über den Parameter fraction
an TypeEvaluator
gesendet. Sie müssen den Interpolator also nicht bei der Berechnung animierter Werte berücksichtigen.
Interpolatoren verwenden
Ein Interpolator definiert, wie bestimmte Werte in einer Animation als Funktion von . Sie können z. B. festlegen, dass Animationen linear über die gesamte Animation laufen, Das heißt, die Animation wird gleichmäßig über die gesamte Zeit bewegt. Sie können aber auch Animationen festlegen, nicht linearen Zeitangaben verwendet, z. B. durch Beschleunigung oder Verzögerung am Anfang oder Ende des Animation.
Interpolatoren im Animationssystem erhalten von Animatoren einen Bruchteil, der die verstrichene Zeit der Animation darstellt. Interpolatoren ändern diesen Bruch, sodass er mit dem Typ
Animation, die es liefern soll. Das Android-System bietet eine Reihe
gemeinsamer Interpolatoren
android.view.animation package
. Wenn keine dieser Optionen Ihren Anforderungen entspricht, können Sie die TimeInterpolator
-Schnittstelle implementieren und Ihre eigene erstellen.
Im Folgenden wird zum Beispiel verglichen, wie der Standardinterpolator AccelerateDecelerateInterpolator
und der LinearInterpolator
interpolierte Brüche berechnen.
LinearInterpolator
hat keine Auswirkungen auf den verstrichenen Bruch. AccelerateDecelerateInterpolator
beschleunigt die Animation und
schneller wieder aus dem Netzwerk raus. Die folgenden Methoden definieren die Logik für diese Interpolatoren:
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; }
In der folgenden Tabelle sind die Näherungswerte aufgeführt, die mithilfe dieser Interpolatoren für eine Animation, die 1.000 ms dauert:
ms verstrichen | Verstrichener/interpolierter Bruch (linear) | Interpolierter Bruch (Beschleunigen/Verlangsamen) |
---|---|---|
0 | 0 | 0 |
200 | 0,2 | 0,1 |
400 | 0,4 | 0,345 |
600 | 0,6 | 0,654 |
800 | 0,8 | 0,9 |
1000 | 1 | 1 |
Wie in der Tabelle zu sehen, ändert LinearInterpolator
die Werte mit derselben Geschwindigkeit, also um 0,2 für alle 200 ms, die vergehen. AccelerateDecelerateInterpolator
ändert die Werte schneller als LinearInterpolator
zwischen 200 ms und 600 ms und langsamer zwischen 600 ms und
1.000 ms.
Keyframes angeben
Ein Keyframe
-Objekt besteht aus einem Zeit/Wert-Paar, mit dem Sie
zu einem bestimmten Zeitpunkt
einer Animation einen bestimmten Zustand erreicht. Jeder Keyframe kann auch einen eigenen
Interpolator ein, um das Verhalten der Animation im Intervall zwischen den vorherigen
der Keyframe-Zeit und die Zeit dieses Keyframes.
Wenn Sie ein Keyframe
-Objekt instanziieren möchten, müssen Sie eine der Fabrikmethoden ofInt()
, ofFloat()
oder ofObject()
verwenden, um den entsprechenden Keyframe
-Typ zu erhalten. Sie rufen dann die ofKeyframe()
-Factorymethode auf, um ein PropertyValuesHolder
-Objekt zu erhalten. Sobald Sie das Objekt haben, können Sie
einen Animationskünstler abrufen, indem Sie das PropertyValuesHolder
-Objekt übergeben und
das zu animierende Objekt. Das folgende Code-Snippet zeigt, wie das geht:
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);
Ansichten animieren
Das Property-Animationssystem ermöglicht eine optimierte Animation von Ansichtsobjekten und bietet einige Vorteile gegenüber dem Ansichts-Animationssystem. Das Ansichtsanimationssystem hat Ansichtsobjekte durch Änderung der Zeichnungsweise transformiert. Dies war im Container jeder View verarbeitet werden, da die View selbst keine Eigenschaften hatte, die geändert werden konnten. Dadurch wurde die Ansicht animiert, das Ansichtsobjekt selbst blieb jedoch unverändert. Dieses führte zum Verhalten eines Objekts, das noch an seinem ursprünglichen Ort existierte, obwohl es an einer anderen Stelle auf dem Bildschirm gezeichnet werden. In Android 3.0 wurden neue Eigenschaften und die entsprechenden Getter- und Setter-Methoden hinzugefügt, um diesen Nachteil zu beheben.
Das Eigenschaftsanimationssystem
können Ansichten auf dem Bildschirm animieren, indem Sie die tatsächlichen Eigenschaften in den View-Objekten ändern. Außerdem wird in Ansichten automatisch die Methode invalidate()
aufgerufen, um das Display zu aktualisieren, wenn sich seine Eigenschaften ändern. Die neuen Properties in der Klasse View
, die die Animationsfunktionen für Properties erleichtern, sind:
translationX
undtranslationY
: Mit diesen Eigenschaften wird gesteuert, Die Ansicht befindet sich als Delta von ihren linken und oberen Koordinaten, die durch ihr Layout festgelegt werden. Container.rotation
,rotationX
undrotationY
: Mit diesen Properties wird die Drehung in 2D (rotation
-Property) und 3D um den Drehpunkt gesteuert.scaleX
undscaleY
: Mit diesen Eigenschaften wird die 2D-Skalierung einer Ansicht um ihren Drehpunkt gesteuert.pivotX
undpivotY
: Mit diesen Eigenschaften wird die Position des Drehpunkts festgelegt, um den herum die Dreh- und Skalierungstransformationen erfolgen. Standardmäßig befindet sich der Drehpunkt in der Mitte des Objekts.x
undy
: Dies sind einfache Dienstprogrammeigenschaften zur Beschreibung des Die endgültige Position der Ansicht in ihrem Container, also als Summe der Werte "left" und "top" TranslationX- und TranslationY-Werte.alpha
: Stellt die Alphatransparenz in der Ansicht dar. Dieser Wert ist 1 (opak) Der Wert 0 steht für vollständige Transparenz (nicht sichtbar).
Zum Animieren einer Eigenschaft eines View-Objekts, etwa der Farbe oder des Rotationswerts, müssen Sie nur erstellen Sie einen Eigenschaftsanimationer und geben die View-Eigenschaft an, die Sie zu animieren. Beispiel:
Kotlin
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f)
Java
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
Weitere Informationen zum Erstellen von Animatoren finden Sie in den Abschnitten zum ValueAnimator und ObjectAnimator:
Mit ViewPropertyAnimator animieren
Mit der ViewPropertyAnimator
können Sie mehrere Eigenschaften eines View
gleichzeitig mit einem einzigen zugrunde liegenden Animator
-Objekt animieren. Es verhält sich ähnlich wie ein ObjectAnimator
, da es die tatsächlichen Werte der Eigenschaften der Ansicht ändert. Es ist jedoch effizienter, wenn viele Eigenschaften gleichzeitig animiert werden. Außerdem ist der Code für die Verwendung von ViewPropertyAnimator
viel prägnanter und leichter zu lesen. Die folgenden Code-Snippets zeigen die Unterschiede bei der Verwendung mehrerer
ObjectAnimator
Objekte, ein einzelnes
ObjectAnimator
und die ViewPropertyAnimator
, wenn
Dabei werden die Eigenschaften x
und y
einer Ansicht gleichzeitig animiert.
Mehrere ObjectAnimator-Objekte
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);
Genauere Informationen zu ViewPropertyAnimator
findest du auf den entsprechenden Android-Entwicklern.
Blog
veröffentlichen.
Animationen in XML deklarieren
Mit dem Eigenschaftsanimationssystem können Sie Eigenschaftsanimationen mit XML deklarieren, die Sie programmatisch nutzen können. Wenn Sie Ihre Animationen in XML definieren, können Sie sie ganz einfach in mehreren Aktivitäten wiederverwenden und die Animationssequenz leichter bearbeiten.
Um Animationen, die die neuen APIs für die Eigenschaftenanimation verwenden, von denen zu unterscheiden, die das alte Framework für die Ansichtsanimation verwenden, sollten Sie ab Android 3.1 die XML-Dateien für die Eigenschaftenanimationen im Verzeichnis res/animator/
speichern.
Die folgenden Property-Animationsklassen unterstützen XML-Deklarationen mit den folgenden XML-Tags:
ValueAnimator
–<animator>
ObjectAnimator
–<objectAnimator>
AnimatorSet
–<set>
Eine Liste der Attribute, die Sie in Ihrer XML-Deklaration verwenden können, finden Sie unter Ressourcen für Animationen. Im folgenden Beispiel werden die beiden Gruppen von Objektanimationen wiedergegeben. nacheinander, wobei der erste verschachtelte Satz zwei Objektanimationen zusammen abspielt:
<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>
Zum Ausführen dieser Animation müssen Sie die XML-Ressourcen in Ihrem Code in ein AnimatorSet
-Objekt aufblähen und dann die Zielobjekte für alle Animationen festlegen.
bevor der Animationssatz gestartet wird. Durch den Aufruf von setTarget()
wird ein einzelnes Zielobjekt für alle untergeordneten Elemente von AnimatorSet
festgelegt. Im folgenden Code wird gezeigt, wie das geht:
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();
Sie können ValueAnimator
auch in XML deklarieren, wie im folgenden Beispiel gezeigt:
<animator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:valueType="floatType" android:valueFrom="0f" android:valueTo="-100f" />
Um die vorherige ValueAnimator
in Ihrem Code zu verwenden, müssen Sie
das Objekt aufblähen muss, ein
AnimatorUpdateListener
,
den aktualisierten Animationswert abrufen
und in einer Property Ihrer Datenansichten verwenden,
Dies wird im folgenden Code dargestellt:
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();
Informationen zur XML-Syntax zum Definieren von Property-Animationen finden Sie unter Animationen.
Mögliche Auswirkungen auf die Leistung der Benutzeroberfläche
Animatoren, die die Benutzeroberfläche aktualisieren, verursachen zusätzliche Rendering-Arbeiten für jeden Frame in auf dem die Animation ausgeführt wird. Daher sollten Sie mit ressourcenintensiven Animationen sich negativ auf die Leistung Ihrer App auswirken kann.
Die für die Animation Ihrer Benutzeroberfläche erforderlichen Arbeiten werden der Animationsphase der Rendering-Pipeline hinzugefügt. Sie können herausfinden, ob sich Ihre Animationen App-Leistung steigern, indem Sie Profil-GPU-Rendering aktivieren und den Animationsbereich überwachen. Weitere Informationen finden Sie unter Profil-GPU-Rendering Schritt-für-Schritt-Anleitung.