Benutzerdefinierte Animationen in Xamarin.Forms

Beispiel herunterladen Das Beispiel herunterladen

Die Animation-Klasse ist der Baustein aller Xamarin.Forms Animationen, wobei die Erweiterungsmethoden in der ViewExtensions-Klasse ein oder mehrere Animation-Objekte erstellen. In diesem Artikel wird veranschaulicht, wie Sie mit der Animationsklasse Animationen erstellen und abbrechen, mehrere Animationen synchronisieren und benutzerdefinierte Animationen erstellen, die Eigenschaften animieren, die nicht von den vorhandenen Animationsmethoden animiert werden.

Beim Erstellen eines Objekts muss eine Animation Reihe von Parametern angegeben werden, einschließlich Start- und Endwerten der animierten Eigenschaft und eines Rückrufs, der den Wert der Eigenschaft ändert. Ein Animation -Objekt kann auch eine Auflistung von untergeordneten Animationen verwalten, die ausgeführt und synchronisiert werden können. Weitere Informationen finden Sie unter Untergeordnete Animationen.

Das Ausführen einer Animation, die mit der Animation -Klasse erstellt wurde, die untergeordnete Animationen enthalten kann oder nicht, wird durch Aufrufen der Commit -Methode erreicht. Diese Methode gibt die Dauer der Animation und unter anderem einen Rückruf an, der steuert, ob die Animation wiederholt werden soll.

Darüber hinaus verfügt die Animation -Klasse über eine IsEnabled -Eigenschaft, die untersucht werden kann, um festzustellen, ob Animationen vom Betriebssystem deaktiviert wurden, z. B. wenn der Energiesparmodus aktiviert ist.

Erstellen einer Animation

Beim Erstellen eines Animation Objekts sind in der Regel mindestens drei Parameter erforderlich, wie im folgenden Codebeispiel veranschaulicht:

var animation = new Animation (v => image.Scale = v, 1, 2);

Dieser Code definiert eine Animation der Scale Eigenschaft eines Image instance von einem Wert von 1 bis zum Wert 2. Der animierte Wert, der von Xamarin.Formsabgeleitet wird, wird an den als erstes Argument angegebenen Rückruf übergeben, wo er verwendet wird, um den Wert der Scale Eigenschaft zu ändern.

Die Animation wird mit einem Aufruf der Commit -Methode gestartet, wie im folgenden Codebeispiel veranschaulicht:

animation.Commit (this, "SimpleAnimation", 16, 2000, Easing.Linear, (v, c) => image.Scale = 1, () => true);

Beachten Sie, dass die Commit -Methode kein Task -Objekt zurückgibt. Stattdessen werden Benachrichtigungen über Rückrufmethoden bereitgestellt.

Die folgenden Argumente werden in der Commit -Methode angegeben:

  • Das erste Argument (Besitzer) identifiziert den Besitzer der Animation. Dies kann das visuelle Element sein, auf das die Animation angewendet wird, oder ein anderes visuelles Element, z. B. die Seite.
  • Das zweite Argument (Name) identifiziert die Animation mit einem Namen. Der Name wird mit dem Besitzer kombiniert, um die Animation eindeutig zu identifizieren. Diese eindeutige Identifizierung kann dann verwendet werden, um zu bestimmen, ob die Animation ausgeführt wird (AnimationIsRunning), oder um sie abzubrechen (AbortAnimation).
  • Das dritte Argument (Rate) gibt die Anzahl von Millisekunden zwischen jedem Aufruf der im Animation Konstruktor definierten Rückrufmethode an.
  • Das vierte Argument (Length) gibt die Dauer der Animation in Millisekunden an.
  • Das fünfte Argument (Easing) definiert die Beschleunigungsfunktion, die in der Animation verwendet werden soll. Alternativ kann die Beschleunigungsfunktion als Argument für den Animation Konstruktor angegeben werden. Weitere Informationen zu Beschleunigungsfunktionen finden Sie unter Beschleunigungsfunktionen.
  • Das sechste Argument (abgeschlossen) ist ein Rückruf, der ausgeführt wird, wenn die Animation abgeschlossen ist. Dieser Rückruf akzeptiert zwei Argumente, wobei das erste Argument einen endgültigen Wert angibt, und das zweite Argument ist ein bool Argument, das auf true festgelegt ist, wenn die Animation abgebrochen wurde. Alternativ kann der fertige Rückruf als Argument für den Animation Konstruktor angegeben werden. Wenn jedoch bei einer einzelnen Animation beendete Rückrufe sowohl im Konstruktor als auch in der AnimationCommit -Methode angegeben werden, wird nur der in der Commit -Methode angegebene Rückruf ausgeführt.
  • Das siebte Argument (Repeat) ist ein Rückruf, mit dem die Animation wiederholt werden kann. Sie wird am Ende der Animation aufgerufen, und die Rückgabe true gibt an, dass die Animation wiederholt werden soll.

Der Gesamteffekt besteht darin, eine Animation zu erstellen, die die Scale Eigenschaft eines Image von 1 auf 2 erhöht, über 2 Sekunden (2000 Millisekunden), wobei die Linear Beschleunigungsfunktion verwendet wird. Jedes Mal, wenn die Animation abgeschlossen ist, wird ihre Scale Eigenschaft auf 1 zurückgesetzt, und die Animation wird wiederholt.

Hinweis

Gleichzeitige Animationen, die unabhängig voneinander ausgeführt werden, können erstellt werden, indem ein Animation Objekt für jede Animation erstellt und dann die Commit -Methode für jede Animation aufgerufen wird.

Untergeordnete Animationen

Die Animation -Klasse unterstützt auch untergeordnete Animationen, wobei ein Animation Objekt erstellt wird, dem andere Animation Objekte hinzugefügt werden. Dadurch kann eine Reihe von Animationen ausgeführt und synchronisiert werden. Das folgende Codebeispiel veranschaulicht das Erstellen und Ausführen untergeordneter Animationen:

var parentAnimation = new Animation ();
var scaleUpAnimation = new Animation (v => image.Scale = v, 1, 2, Easing.SpringIn);
var rotateAnimation = new Animation (v => image.Rotation = v, 0, 360);
var scaleDownAnimation = new Animation (v => image.Scale = v, 2, 1, Easing.SpringOut);

parentAnimation.Add (0, 0.5, scaleUpAnimation);
parentAnimation.Add (0, 1, rotateAnimation);
parentAnimation.Add (0.5, 1, scaleDownAnimation);

parentAnimation.Commit (this, "ChildAnimations", 16, 4000, null, (v, c) => SetIsEnabledButtonState (true, false));

Alternativ kann das Codebeispiel präziser geschrieben werden, wie im folgenden Codebeispiel veranschaulicht:

new Animation {
    { 0, 0.5, new Animation (v => image.Scale = v, 1, 2) },
    { 0, 1, new Animation (v => image.Rotation = v, 0, 360) },
    { 0.5, 1, new Animation (v => image.Scale = v, 2, 1) }
    }.Commit (this, "ChildAnimations", 16, 4000, null, (v, c) => SetIsEnabledButtonState (true, false));

In beiden Codebeispielen wird ein übergeordnetes Animation Objekt erstellt, dem dann zusätzliche Animation Objekte hinzugefügt werden. Die ersten beiden Argumente für die Add -Methode geben an, wann die untergeordnete Animation gestartet und beendet werden soll. Die Argumentwerte müssen zwischen 0 und 1 sein und den relativen Zeitraum innerhalb der übergeordneten Animation darstellen, in dem die angegebene untergeordnete Animation aktiv ist. Daher ist in diesem Beispiel die scaleUpAnimation für die erste Hälfte der Animation aktiv, die scaleDownAnimation ist für die zweite Hälfte der Animation aktiv, und die rotateAnimation ist für die gesamte Dauer aktiv.

Der Gesamteffekt ist, dass die Animation über 4 Sekunden (4000 Millisekunden) erfolgt. Die scaleUpAnimation animiert die Scale Eigenschaft von 1 bis 2, über 2 Sekunden. Die scaleDownAnimation animiert dann die Scale Eigenschaft von 2 auf 1, über 2 Sekunden. Während beide Skalierungsanimationen ausgeführt werden, wird die rotateAnimationRotation Eigenschaft von 0 auf 360 animiert, und das über 4 Sekunden. Beachten Sie, dass die Skalierungsanimationen auch Beschleunigungsfunktionen verwenden. Die SpringIn Easing-Funktion bewirkt, dass die Image zuerst verkleinern, bevor sie größer wird, und die SpringOut Beschleunigungsfunktion bewirkt, dass die Image gegen Ende der vollständigen Animation kleiner als ihre tatsächliche Größe wird.

Es gibt eine Reihe von Unterschieden zwischen einem Animation Objekt, das untergeordnete Animationen verwendet, und einem Objekt, das nicht:

  • Bei Verwendung untergeordneter Animationen gibt der fertige Rückruf für eine untergeordnete Animation an, wann das untergeordnete Element abgeschlossen ist, und der an die Commit -Methode übergebene fertige Rückruf gibt an, wann die gesamte Animation abgeschlossen ist.
  • Wenn Sie untergeordnete Animationen verwenden, führt die Rückgabe true vom Wiederholungsrückruf für die Commit -Methode nicht dazu, dass sich die Animation wiederholt, aber die Animation wird weiterhin ohne neue Werte ausgeführt.
  • Wenn sie eine Beschleunigungsfunktion in die Commit -Methode einschließt und die Beschleunigungsfunktion einen Wert größer als 1 zurückgibt, wird die Animation beendet. Wenn die Beschleunigungsfunktion einen Wert kleiner als 0 zurückgibt, wird der Wert auf 0 geklemmt. Um eine Beschleunigungsfunktion zu verwenden, die einen Wert kleiner als 0 oder größer als 1 zurückgibt, muss sie in einer der untergeordneten Animationen und nicht in der Commit -Methode angegeben werden.

Die Animation -Klasse enthält WithConcurrent auch Methoden, mit denen einem übergeordneten Animation Objekt untergeordnete Animationen hinzugefügt werden können. Die Werte des Anfangs- und Endarguments sind jedoch nicht auf 0 bis 1 beschränkt, sondern nur der Teil der untergeordneten Animation, der einem Bereich von 0 bis 1 entspricht, ist aktiv. Wenn beispielsweise ein WithConcurrent Methodenaufruf eine untergeordnete Animation definiert, die auf eine Scale Eigenschaft von 1 bis 6 abzielt, aber mit Anfangs- und Endwerten von -2 und 3, entspricht der Anfangswert von -2 dem Scale Wert 1 und der Endwert von 3 einem Scale Wert von 6. Da Werte außerhalb des Bereichs von 0 und 1 keine Rolle in einer Animation spielen, wird die Scale Eigenschaft nur von 3 bis 6 animiert.

Abbrechen einer Animation

Eine Anwendung kann eine Animation mit einem Aufruf der AbortAnimation Erweiterungsmethode abbrechen, wie im folgenden Codebeispiel veranschaulicht:

this.AbortAnimation ("SimpleAnimation");

Beachten Sie, dass Animationen durch eine Kombination aus dem Animationsbesitzer und dem Animationsnamen eindeutig identifiziert werden. Daher müssen der Besitzer und name angegeben werden, der beim Ausführen der Animation angegeben wurde, um die Animation abzubrechen. Daher wird im Codebeispiel sofort die Animation mit dem Namen SimpleAnimation abgebrochen, die sich im Besitz der Seite befindet.

Erstellen einer benutzerdefinierten Animation

Die bisher gezeigten Beispiele haben Animationen gezeigt, die mit den Methoden in der ViewExtensions Klasse gleichermaßen erreicht werden konnten. Der Vorteil der Animation Klasse besteht jedoch darin, dass sie Zugriff auf die Rückrufmethode hat, die ausgeführt wird, wenn sich der animierte Wert ändert. Dadurch kann der Rückruf jede gewünschte Animation implementieren. Im folgenden Codebeispiel wird beispielsweise die BackgroundColor Eigenschaft einer Seite animiert, indem sie auf Color Werte festgelegt wird, die von der Methode erstellt wurden, wobei farbtonwerte Color.FromHsla von 0 bis 1 reichen:

new Animation (callback: v => BackgroundColor = Color.FromHsla (v, 1, 0.5),
  start: 0,
  end: 1).Commit (this, "Animation", 16, 4000, Easing.Linear, (v, c) => BackgroundColor = Color.Default);

Die resultierende Animation bietet das Erscheinungsbild, wie der Seitenhintergrund durch die Farben des Regenbogens vorgerückt wird.

Weitere Beispiele zum Erstellen komplexer Animationen, einschließlich einer Bézierkurvenanimation, finden Sie in Kapitel 22 des Erstellens mobiler Apps mit Xamarin.Forms.

Erstellen einer benutzerdefinierten Animationserweiterungsmethode

Die Erweiterungsmethoden in der ViewExtensions -Klasse animieren eine Eigenschaft vom aktuellen Wert zu einem angegebenen Wert. Dies macht es schwierig, z. B. eine ColorTo Animationsmethode zu erstellen, die verwendet werden kann, um eine Farbe von einem Wert zum anderen zu animieren, da:

  • Die einzige Color von der VisualElement -Klasse definierte Eigenschaft ist BackgroundColor, was nicht immer die gewünschte Color Eigenschaft ist, die animiert werden soll.
  • Häufig ist Color.Defaultder aktuelle Wert einer Color Eigenschaft , die keine echte Farbe ist und nicht in Interpolationsberechnungen verwendet werden kann.

Die Lösung für dieses Problem besteht darin, dass die ColorTo Methode keine bestimmte Color Eigenschaft als Ziel hat. Stattdessen kann es mit einer Rückrufmethode geschrieben werden, die den interpolierten Color Wert zurück an den Aufrufer übergibt. Darüber hinaus akzeptiert die -Methode Start- und Endargumente Color .

Die ColorTo -Methode kann als Erweiterungsmethode implementiert werden, die die Animate -Methode in der AnimationExtensions -Klasse verwendet, um ihre Funktionalität bereitzustellen. Dies liegt daran, dass die Animate -Methode für Zieleigenschaften verwendet werden kann, die nicht vom Typ doublesind, wie im folgenden Codebeispiel veranschaulicht:

public static class ViewExtensions
{
  public static Task<bool> ColorTo(this VisualElement self, Color fromColor, Color toColor, Action<Color> callback, uint length = 250, Easing easing = null)
  {
    Func<double, Color> transform = (t) =>
      Color.FromRgba(fromColor.R + t * (toColor.R - fromColor.R),
                     fromColor.G + t * (toColor.G - fromColor.G),
                     fromColor.B + t * (toColor.B - fromColor.B),
                     fromColor.A + t * (toColor.A - fromColor.A));
    return ColorAnimation(self, "ColorTo", transform, callback, length, easing);
  }

  public static void CancelAnimation(this VisualElement self)
  {
    self.AbortAnimation("ColorTo");
  }

  static Task<bool> ColorAnimation(VisualElement element, string name, Func<double, Color> transform, Action<Color> callback, uint length, Easing easing)
  {
    easing = easing ?? Easing.Linear;
    var taskCompletionSource = new TaskCompletionSource<bool>();

    element.Animate<Color>(name, transform, callback, 16, length, easing, (v, c) => taskCompletionSource.SetResult(c));
    return taskCompletionSource.Task;
  }
}

Die Animate -Methode erfordert ein Transformationsargument , bei dem es sich um eine Rückrufmethode handelt. Die Eingabe für diesen Rückruf ist immer zwischen double 0 und 1. Daher definiert die ColorTo -Methode eine eigene Transformation Func , die einen double Wert von 0 bis 1 akzeptiert und einen Color Wert zurückgibt, der diesem Wert entspricht. Der Color Wert wird berechnet, indem die RWerte , , Gund BA der beiden angegebenen Color Argumente interpoliert werden. Der Color Wert wird dann an die Rückrufmethode für die Anwendung an eine bestimmte Eigenschaft übergeben.

Mit diesem Ansatz kann die ColorTo Methode jede Eigenschaft Color animieren, wie im folgenden Codebeispiel veranschaulicht:

await Task.WhenAll(
  label.ColorTo(Color.Red, Color.Blue, c => label.TextColor = c, 5000),
  label.ColorTo(Color.Blue, Color.Red, c => label.BackgroundColor = c, 5000));
await this.ColorTo(Color.FromRgb(0, 0, 0), Color.FromRgb(255, 255, 255), c => BackgroundColor = c, 5000);
await boxView.ColorTo(Color.Blue, Color.Red, c => boxView.Color = c, 4000);

In diesem Codebeispiel animiert die ColorTo -Methode die TextColor - und BackgroundColor -Eigenschaften eines Label, der BackgroundColor -Eigenschaft einer -Seite und der Color -Eigenschaft eines BoxView.