Udostępnij za pośrednictwem


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 na true wartość , jeśli animacja została anulowana. Alternatywnie można określić zakończone wywołanie zwrotne jako argument konstruktora Animation . Jednak w przypadku pojedynczej animacji, jeśli zakończone wywołania zwrotne są określone zarówno w konstruktorze Animation , jak i metodzie Commit , zostanie wykonane tylko wywołanie zwrotne określone w Commit 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ń w Commit 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 metodzie Commit .

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 jest BackgroundColor, która nie zawsze jest żądaną Color właściwością do animowania.
  • Często bieżąca wartość Color właściwości to Color.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ę Rwartości , , GBi 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 Labeli BackgroundColor obiektu , BackgroundColor właściwość strony i Color właściwość BoxView.