Freigeben über


Benutzerdefinierte Animationen in Xamarin.Forms

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

Bei der Erstellung eines Animation-Objekts muss eine Reihe von Parametern angegeben werden, darunter Start- und Endwerte der zu animierenden Eigenschaft und ein Rückruf, der den Wert der Eigenschaft ändert. Ein Animation-Objekt kann auch eine Sammlung von untergeordneten Animationen verwalten, die ausgeführt und synchronisiert werden können. Weitere Informationen finden Sie unter untergeordnete Animationen.

Die Ausführung einer mit der Klasse Animation erstellten Animation, die auch untergeordnete Animationen enthalten kann, wird durch den Aufruf der Methode Commit 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. beim Aktivieren des Energiesparmodus.

Erstellen einer Animation

Bei der Erstellung eines Animation-Objekts sind in der Regel mindestens drei Parameter erforderlich, wie das folgende Codebeispiel zeigt:

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

Dieser Code definiert eine Animation der Scale Eigenschaft einer Image Instanz von einem Wert von 1 bis zu einem Wert von 2. Der animierte Wert, der von Xamarin.Formsdiesem abgeleitet wird, wird an den als erstes Argument angegebenen Rückruf übergeben, in dem 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 Objekt zurückgibt Task . Stattdessen werden die Benachrichtigungen über Callback-Methoden bereitgestellt.

Die folgenden Argumente werden in der Methode Commit 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, wie etwa die Seite.
  • Das zweite Argument (Name) identifiziert die Animation mit einem Namen. Der Name wird mit dem Eigentümer kombiniert, um die Animation eindeutig zu identifizieren. Anhand dieser eindeutigen Bezeichnung kann dann festgestellt werden, ob die Animation läuft (AnimationIsRunning), oder sie kann abgebrochen werden (AbortAnimation).
  • Das dritte Argument (Rate) gibt die Anzahl von Millisekunden zwischen jedem Aufruf der im Animation Konstruktor definierten Rückrufmethode an.
  • Das vierte Argument (Länge) gibt die Dauer der Animation in Millisekunden an.
  • Das fünfte Argument (Beschleunigung) definiert die Beschleunigungsfunktion, die in der Animation verwendet werden soll. Alternativ kann die Beschleunigungsfunktion auch als Argument für den Animation-Konstruktor angegeben werden. Weitere Informationen zu Beschleunigungsfunktionen finden Sie unter Beschleunigungsfunktionen.
  • Das sechste Argument (fertig) ist ein Rückruf, der ausgeführt wird, wenn die Animation abgeschlossen ist. Dieser Rückruf nimmt zwei Argumente entgegen, wobei das erste Argument einen Endwert angibt und das zweite Argument ein bool ist, das auf true gesetzt wird, wenn die Animation abgebrochen wurde. Alternativ kann der fertige Rückruf als Argument für den Animation Konstruktor angegeben werden. Bei einer einzelnen Animation werden jedoch, wenn fertige Rückrufe sowohl im Konstruktor als auch Animation in der Commit Methode angegeben sind, nur der in der Commit Methode angegebene Rückruf ausgeführt.
  • Das siebte Argument (Wiederholen) ist ein Rückruf, der die Wiederholung der Animation zulässt. Es wird am Ende der Animation aufgerufen, und die Rückgabe von true zeigt an, dass die Animation wiederholt werden soll.

Der Gesamteffekt besteht darin, eine Animation zu erstellen, die die Scale Eigenschaft einer Image von 1 auf 2, über 2 Sekunden (2000 Millisekunden) mit der Linear Beschleunigungsfunktion erhöht. 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 ablaufen, können erstellt werden, indem man für jede Animation ein Animation-Objekt erstellt und dann die Commit-Methode für jede Animation aufruft.

Untergeordnete Animationen

Die Animation Klasse unterstützt auch untergeordnete Animationen, bei denen ein Objekt erstellt Animation wird, dem andere Animation Objekte hinzugefügt werden. So kann eine Reihe von Animationen ausgeführt und synchronisiert werden. Das folgende Codebeispiel veranschaulicht die Erstellung und Ausführung von untergeordneten 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 gezeigt:

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 der Methode Add geben an, wann die untergeordnete Animation beginnen und enden soll. Die Werte der Argumente müssen zwischen 0 und 1 liegen und stellen den relativen Zeitraum innerhalb der übergeordneten Animation dar, in dem die angegebene untergeordnete Animation aktiv sein wird. In diesem Beispiel ist scaleUpAnimation also für die erste Hälfte der Animation aktiv, scaleDownAnimation für die zweite Hälfte der Animation und rotateAnimation für die gesamte Dauer.

Der Gesamteffekt besteht darin, dass die Animation über 4 Sekunden (4000 Millisekunden) erfolgt. Die scaleUpAnimation animiert die Scale Eigenschaft von 1 auf 2, über 2 Sekunden. Die scaleDownAnimation animiert dann die Scale-Eigenschaft von 2 auf 1, über 2 Sekunden. Während beide Skalierungsanimationen ablaufen, animiert die rotateAnimation die Rotation-Eigenschaft über 4 Sekunden von 0 bis 360. Beachten Sie, dass die Skalierungsanimationen auch Beschleunigungsfunktionen verwenden. Die SpringIn Beschleunigungsfunktion bewirkt, dass die Image Beschleunigungsfunktion zunächst verkleinern wird, bevor sie größer wird, und die SpringOut Beschleunigungsfunktion bewirkt, dass die Image tatsächliche Größe am Ende der vollständigen Animation kleiner wird.

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

  • 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 Rückruf gibt an, wann die gesamte Animation abgeschlossen ist.
  • Wenn Sie untergeordnete Animationen verwenden, führt die Rückgabe des Wiederholten Rückrufs true für die Commit Methode nicht dazu, dass die Animation wiederholt wird, aber die Animation wird weiterhin ohne neue Werte ausgeführt.
  • Wenn eine Beschleunigungsfunktion in die Commit-Methode eingebunden wird und die Lockerungsfunktion einen Wert größer als 1 zurückgibt, wird die Animation abgebrochen. 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 Methode Commit angegeben werden.

Die Animation-Klasse enthält auch WithConcurrent-Methoden, die verwendet werden können, um einem übergeordneten Animation-Objekt untergeordnete Animationen hinzuzufügen. Die Anfangs - und Endargumentwerte 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 ein WithConcurrent Methodenaufruf z. B. eine untergeordnete Animation definiert, die auf eine Scale Eigenschaft von 1 bis 6 ausgerichtet ist, aber mit den Anfangs- und Endwerten von -2 und 3 entspricht der Anfangswert von -2 einem Scale Wert von 1, und der Endwert von 3 entspricht einem Scale Wert von 6. Da Werte außerhalb des Bereichs von 0 und 1 bei einer Animation keine Rolle spielen, wird die Eigenschaft Scale 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 des Animationsbesitzers und den Animationsnamen eindeutig identifiziert werden. Daher muss der Beim Ausführen der Animation angegebene Besitzer und Name angegeben werden, um die Animation abzubrechen. Daher wird die Animation SimpleAnimation , die im Besitz der Seite ist, sofort abgebrochen.

Erstellen einer benutzerdefinierten Animation

Die bisher gezeigten Beispiele haben Animationen gezeigt, die auch mit den Methoden der Klasse ViewExtensions erreicht werden können. Der Vorteil der Klasse Animation besteht jedoch darin, dass sie Zugriff auf die Callback-Methode hat, die ausgeführt wird, wenn sich der animierte Wert ändert. Dadurch kann der Callback jede gewünschte Animation implementieren. Das folgende Codebeispiel animiert beispielsweise die BackgroundColor-Eigenschaft einer Seite, indem sie auf Color-Werte gesetzt wird, die mit der Color.FromHsla-Methode erstellt wurden, wobei die Farbtonwerte 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 daraus resultierende Animation erweckt den Anschein, dass der Seitenhintergrund durch die Farben des Regenbogens fortschreitet.

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

Erstellen einer benutzerdefinierten Erweiterungsmethode für Animationen

Die Erweiterungsmethoden in der Klasse ViewExtensions animieren eine Eigenschaft von ihrem aktuellen Wert zu einem bestimmten Wert. Dies macht es schwierig, beispielsweise eine ColorTo Animationsmethode zu erstellen, die zum Animieren einer Farbe von einem Wert zu einem anderen verwendet werden kann, 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 eine echte Farbe, die in Interpolationsberechnungen nicht verwendet werden kann.

Die Lösung für dieses Problem besteht darin, dass die ColorTo-Methode nicht auf eine bestimmte Color-Eigenschaft abzielt. Stattdessen kann sie mit einer Rückruf-Methode geschrieben werden, die den interpolierten Color-Wert an den Aufrufer zurückgibt. Darüber hinaus erhält 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 verwendet werden kann, um auf Eigenschaften zu zielen, die nicht vom Typ double sind, wie im folgenden Codebeispiel gezeigt wird:

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;
  }
}

Für die Animate Methode ist ein Transformationsargument erforderlich, bei dem es sich um eine Rückrufmethode handelt. Die Eingabe für diesen Rückruf ist immer ein double im Bereich von 0 bis 1. Daher definiert die ColorTo Methode eine eigene Transformation Func , die einen double Bereich von 0 bis 1 akzeptiert und einen Color Wert zurückgibt, der diesem Wert entspricht. Der Color-Wert wird durch Interpolation der R-, G-, B- und A-Werte der beiden gelieferten Color-Argumente berechnet. 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 Color Eigenschaft animieren, wie im folgenden Codebeispiel gezeigt:

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 Methode ColorTo die Eigenschaften TextColor und BackgroundColor eines Label, die Eigenschaft BackgroundColor einer Seite und die Eigenschaft Color eines BoxView.