Attributanimation – Übersicht

Compose ausprobieren
Jetpack Compose ist das empfohlene UI-Toolkit für Android. Weitere Informationen zur Verwendung von Animationen in „Compose“

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.

Abbildung 1: Beispiel für eine lineare Animation

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.

Abbildung 2. Beispiel für eine nicht lineare Animation

Sehen wir uns genauer an, wie die wichtigen Komponenten des Animationen wie die oben dargestellten berechnet. Abbildung 3 zeigt, wie die Hauptklassen miteinander zusammenarbeiten.

Abbildung 3: Berechnung von Animationen

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:

Tabelle 1 Animatoren

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:

Tabelle 2: Evaluierende

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.

Tabelle 3 Interpolatoren

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 die ObjectAnimator 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 beispielsweise foo, müssen Sie haben eine setFoo()-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 der ObjectAnimator-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 Format get<PropertyName>() haben. Wenn der Property-Name beispielsweise foo lautet, benötigen Sie die Methode getFoo().
  • 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ötigen targetObject.setPropName(float) und targetObject.getPropName(), wenn Sie die folgende ObjectAnimator 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 der onAnimationUpdate() 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() und setTranslationX(), 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:

  1. bounceAnim wird abgespielt.
  2. squashAnim1, squashAnim2, stretchAnim1 und stretchAnim2.
  3. Klingelt in bounceBackAnim.
  4. 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
  • ValueAnimator.AnimatorUpdateListener
    • onAnimationUpdate() wird bei jedem Frame der Animation aufgerufen. Dieses Ereignis überwachen, um die von ValueAnimator während eines Animation. Wenn du den Wert verwenden möchtest, musst du das ValueAnimator-Objekt abfragen, das an das Ereignis übergeben wurde, um den aktuellen animierten Wert mit der Methode getAnimatedValue() abzurufen. Die Implementierung dieser Listener ist erforderlich, wenn Sie ValueAnimator 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() und setTranslationX() 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:

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>

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 und translationY: 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 und rotationY: Mit diesen Properties wird die Drehung in 2D (rotation-Property) und 3D um den Drehpunkt gesteuert.
  • scaleX und scaleY: Mit diesen Eigenschaften wird die 2D-Skalierung einer Ansicht um ihren Drehpunkt gesteuert.
  • pivotX und pivotY: 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 und y: 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:

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.