Animacje niestandardowe w programie Xamarin.Forms
Klasa Animation jest blokiem konstrukcyjnym wszystkich Xamarin.Forms animacji, z metodami rozszerzenia w klasie ViewExtensions tworzącym co najmniej jeden obiekt Animacja. W tym artykule pokazano, jak używać klasy Animacja do tworzenia i anulowania animacji, synchronizowania wielu animacji i tworzenia niestandardowych animacji, które animują właściwości, które nie są animowane przez istniejące metody animacji.
Podczas tworzenia Animation
obiektu należy określić szereg parametrów, w tym wartości początkowe i końcowe właściwości animowanej oraz wywołanie zwrotne, które zmienia wartość właściwości. Obiekt Animation
może również obsługiwać kolekcję animacji podrzędnych, które można uruchamiać i synchronizować. Aby uzyskać więcej informacji, zobacz Animacje podrzędne.
Uruchomienie animacji utworzonej Animation
za pomocą klasy , która może lub nie może zawierać animacji podrzędnych, jest osiągana przez wywołanie Commit
metody . Ta metoda określa czas trwania animacji, a wśród innych elementów wywołanie zwrotne, które kontroluje, czy powtarzać animację.
Ponadto klasa ma IsEnabled
właściwość, którą można zbadać, aby określić, Animation
czy animacje zostały wyłączone przez system operacyjny, na przykład w przypadku aktywowania trybu oszczędzania energii.
Tworzenie animacji
Podczas tworzenia Animation
obiektu zwykle wymagane są co najmniej trzy parametry, jak pokazano w poniższym przykładzie kodu:
var animation = new Animation (v => image.Scale = v, 1, 2);
Ten kod definiuje animację Scale
właściwości Image
wystąpienia z wartości 1 do wartości 2. Animowana wartość, która jest pochodna przez Xamarin.Formselement , jest przekazywana do wywołania zwrotnego określonego jako pierwszy argument, gdzie służy do zmiany wartości Scale
właściwości.
Animacja jest uruchamiana z wywołaniem Commit
metody, jak pokazano w poniższym przykładzie kodu:
animation.Commit (this, "SimpleAnimation", 16, 2000, Easing.Linear, (v, c) => image.Scale = 1, () => true);
Należy pamiętać, że Commit
metoda nie zwraca Task
obiektu. Zamiast tego powiadomienia są dostarczane za pomocą metod wywołania zwrotnego.
W metodzie Commit
określono następujące argumenty:
- Pierwszy argument (właściciel) identyfikuje właściciela animacji. Może to być element wizualizacji, na którym jest stosowana animacja, lub inny element wizualizacji, taki jak strona.
- Drugi argument (nazwa) identyfikuje animację o nazwie. Nazwa jest łączona z właścicielem w celu unikatowego zidentyfikowania animacji. Tej unikatowej identyfikacji można następnie użyć do określenia, czy animacja jest uruchomiona (
AnimationIsRunning
), czy też ją anulować (AbortAnimation
). - Trzeci argument (rate) wskazuje liczbę milisekund między każdym wywołaniem metody wywołania zwrotnego zdefiniowanej w konstruktorze
Animation
. - Czwarty argument (długość) wskazuje czas trwania animacji w milisekundach.
- Piąty argument (złagodzenie) definiuje funkcję złagodzenia, która ma być używana w animacji. Alternatywnie funkcję złagodzenia można określić jako argument konstruktora
Animation
. Aby uzyskać więcej informacji na temat funkcji ułatwiania, zobacz Easing Functions (Funkcje easing). - Szósty argument (zakończone) to wywołanie zwrotne, które zostanie wykonane po zakończeniu animacji. To wywołanie zwrotne przyjmuje dwa argumenty, z pierwszym argumentem wskazującym wartość końcową, a drugi argument jest
bool
ustawiony natrue
wartość , jeśli animacja została anulowana. Alternatywnie można określić zakończone wywołanie zwrotne jako argument konstruktoraAnimation
. Jednak w przypadku pojedynczej animacji, jeśli zakończone wywołania zwrotne są określone zarówno w konstruktorzeAnimation
, jak i metodzieCommit
, zostanie wykonane tylko wywołanie zwrotne określone wCommit
metodzie. - Siódmy argument (powtórzenie) to wywołanie zwrotne, które umożliwia powtarzanie animacji. Jest wywoływana na końcu animacji i zwracana
true
wskazuje, że animacja powinna być powtarzana.
Ogólny efekt polega na utworzeniu animacji, która zwiększa Scale
właściwość Image
z zakresu od 1 do 2, ponad 2 sekund (2000 milisekund), używając Linear
funkcji złagodzenia. Za każdym razem, gdy animacja zostanie ukończona, jej Scale
właściwość zostanie zresetowana do wartości 1, a animacja będzie powtarzana.
Uwaga
Współbieżne animacje, które są uruchamiane niezależnie od siebie, można utworzyć przez utworzenie Animation
obiektu dla każdej animacji, a następnie wywołanie Commit
metody dla każdej animacji.
Animacje podrzędne
Klasa Animation
obsługuje również animacje podrzędne, które obejmują utworzenie Animation
obiektu, do którego dodawane są inne Animation
obiekty. Dzięki temu można uruchamiać i synchronizować serię animacji. W poniższym przykładzie kodu pokazano tworzenie i uruchamianie animacji podrzędnych:
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));
Alternatywnie przykład kodu można napisać bardziej zwięzłie, jak pokazano w poniższym przykładzie kodu:
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));
W obu przykładach kodu tworzony jest obiekt nadrzędny Animation
, do którego są następnie dodawane dodatkowe Animation
obiekty. Pierwsze dwa argumenty Add
metody określają, kiedy rozpocząć i zakończyć animację podrzędną. Wartości argumentów muszą należeć do przedziału od 0 do 1 i reprezentować względny okres w animacji nadrzędnej, że określona animacja podrzędna będzie aktywna. W związku z tym w tym przykładzie scaleUpAnimation
wartość będzie aktywna w pierwszej połowie animacji, scaleDownAnimation
wartość będzie aktywna przez drugą połowę animacji i rotateAnimation
będzie aktywna przez cały czas trwania.
Ogólny efekt polega na tym, że animacja występuje ponad 4 sekundy (4000 milisekund). Obiekt scaleUpAnimation
animuje Scale
właściwość z zakresu od 1 do 2, ponad 2 sekundy. Następnie scaleDownAnimation
animuje Scale
właściwość z 2 do 1, ponad 2 sekundy. Podczas gdy obie animacje skalowania występują, rotateAnimation
właściwość animuje Rotation
właściwość z zakresu od 0 do 360, ponad 4 sekundy. Należy pamiętać, że animacje skalowania używają również funkcji złagodzenia. Funkcja SpringIn
złagodzenia powoduje Image
, że początkowo kurczy się przed uzyskaniem większego rozmiaru, a SpringOut
funkcja złagodzenia powoduje Image
, że wartość staje się mniejsza niż jej rzeczywisty rozmiar na końcu pełnej animacji.
Istnieje wiele różnic między obiektem Animation
, który używa animacji podrzędnych, i taki, który nie:
- W przypadku korzystania z animacji podrzędnych zakończone wywołanie zwrotne w animacji podrzędnej wskazuje, kiedy element podrzędny został ukończony, a zakończone wywołanie zwrotne przekazane do
Commit
metody wskazuje, kiedy cała animacja została ukończona. - W przypadku korzystania z animacji podrzędnych powrót
true
z wywołania zwrotnego powtórzeń wCommit
metodzie nie spowoduje powtórzenia animacji, ale animacja będzie nadal działać bez nowych wartości. - W przypadku włączenia funkcji złagodzenia w metodzie
Commit
, a funkcja easing zwraca wartość większą niż 1, animacja zostanie zakończona. Jeśli funkcja złagodzenia zwraca wartość mniejszą niż 0, wartość jest zaciśnięta do 0. Aby użyć funkcji złagodzenia, która zwraca wartość mniejszą niż 0 lub większą niż 1, musi ona być określona w jednej z animacji podrzędnych, a nie w metodzieCommit
.
Klasa Animation
zawiera WithConcurrent
również metody, których można użyć do dodawania animacji podrzędnych do obiektu nadrzędnego Animation
. Jednak ich wartości argumentów rozpoczęcia i zakończenia nie są ograniczone do 0 do 1, ale tylko ta część animacji podrzędnej, która odpowiada zakresowi od 0 do 1, będzie aktywna. Jeśli na przykład WithConcurrent
wywołanie metody definiuje animację podrzędną, która jest przeznaczona Scale
dla właściwości z zakresu od 1 do 6, ale z wartościami rozpoczęcia i zakończenia -2 i 3, wartość początek -2 odpowiada Scale
wartości 1, a wartość zakończenia 3 odpowiada Scale
wartości 6. Ponieważ wartości spoza zakresu od 0 do 1 nie odgrywają żadnej części w animacji, Scale
właściwość będzie animowana tylko z zakresu od 3 do 6.
Anulowanie animacji
Aplikacja może anulować animację z wywołaniem AbortAnimation
metody rozszerzenia, jak pokazano w poniższym przykładzie kodu:
this.AbortAnimation ("SimpleAnimation");
Należy pamiętać, że animacje są jednoznacznie identyfikowane przez kombinację właściciela animacji i nazwę animacji. W związku z tym właściciel i nazwa określona podczas uruchamiania animacji należy określić, aby anulować animację. W związku z tym przykład kodu natychmiast anuluje animację o nazwie SimpleAnimation
należącej do strony.
Tworzenie animacji niestandardowej
W przedstawionych tutaj przykładach pokazano do tej pory animacje, które można osiągnąć w równym stopniu przy użyciu metod w ViewExtensions
klasie. Jednak zaletą Animation
klasy jest to, że ma dostęp do metody wywołania zwrotnego, która jest wykonywana po zmianie animowanej wartości. Dzięki temu wywołanie zwrotne może zaimplementować dowolną żądaną animację. Na przykład poniższy przykład kodu animuje BackgroundColor
właściwość strony, ustawiając ją na wartości utworzone przez Color.FromHsla
metodę, z wartościami odcieni od 0 do Color
1:
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);
Wynikowa animacja zapewnia wygląd tła strony przez kolory tęczy.
Aby uzyskać więcej przykładów tworzenia złożonych animacji, w tym animacji krzywej Beziera, zobacz rozdział 22 tworzenie aplikacji mobilnych za pomocą Xamarin.Formsprogramu .
Tworzenie niestandardowej metody rozszerzenia animacji
Metody rozszerzeń w ViewExtensions
klasie animują właściwość z bieżącej wartości na określoną wartość. Utrudnia to na przykład utworzenie metody animacji, ColorTo
która może służyć do animowania koloru z jednej wartości na drugą, ponieważ:
- Jedyną
Color
właściwością zdefiniowaną przez klasęVisualElement
jestBackgroundColor
, która nie zawsze jest żądanąColor
właściwością do animowania. - Często bieżąca wartość
Color
właściwości toColor.Default
, która nie jest rzeczywistym kolorem i której nie można używać w obliczeniach interpolacji.
Rozwiązaniem tego problemu jest brak ColorTo
właściwości docelowej Color
metody. Zamiast tego można go napisać za pomocą metody wywołania zwrotnego, która przekazuje wartość interpolowaną Color
z powrotem do elementu wywołującego. Ponadto metoda będzie przyjmować argumenty początkowe i końcowe Color
.
Metodę ColorTo
można zaimplementować jako metodę rozszerzenia, która używa Animate
metody w AnimationExtensions
klasie w celu zapewnienia jej funkcjonalności. Jest to spowodowane tym, że Animate
metoda może służyć do określania właściwości docelowych, które nie są typu double
, jak pokazano w poniższym przykładzie kodu:
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;
}
}
Metoda Animate
wymaga argumentu przekształcenia , który jest metodą wywołania zwrotnego. Dane wejściowe tego wywołania zwrotnego są zawsze double
od 0 do 1. W związku z tym ColorTo
metoda definiuje własną transformację Func
, która akceptuje double
wartość z zakresu od 0 do 1 i która zwraca wartość odpowiadającą Color
tej wartości. Wartość Color
jest obliczana przez interpolację R
wartości , , G
B
i A
dwóch podanych Color
argumentów. Następnie Color
wartość jest przekazywana do metody wywołania zwrotnego dla aplikacji do określonej właściwości.
Takie podejście umożliwia metodę ColorTo
animowania dowolnej Color
właściwości, jak pokazano w poniższym przykładzie kodu:
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);
W tym przykładzie ColorTo
kodu metoda animuje TextColor
właściwości Label
i BackgroundColor
obiektu , BackgroundColor
właściwość strony i Color
właściwość BoxView
.