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 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 auftrue
festgelegt ist, wenn die Animation abgebrochen wurde. Alternativ kann der fertige Rückruf als Argument für denAnimation
Konstruktor angegeben werden. Wenn jedoch bei einer einzelnen Animation beendete Rückrufe sowohl im Konstruktor als auch in derAnimation
Commit
-Methode angegeben werden, wird nur der in derCommit
-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 rotateAnimation
Rotation
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 dieCommit
-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 derCommit
-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 derVisualElement
-Klasse definierte Eigenschaft istBackgroundColor
, was nicht immer die gewünschteColor
Eigenschaft ist, die animiert werden soll. - Häufig ist
Color.Default
der aktuelle Wert einerColor
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 double
sind, 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 R
Werte , , G
und B
A
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
.