Sdílet prostřednictvím


Vlastní animace

Třída .NET Multi-Platform App UI (.NET MAUI) Animation je stavební blok všech animací .NET MAUI s metodami rozšíření ve ViewExtensions třídě, které vytvářejí jeden nebo více Animation objektů.

Při vytváření objektu Animation , včetně počátečních a koncových hodnot animované vlastnosti, a zpětného volání, které změní hodnotu vlastnosti, musí být zadáno několik parametrů. Objekt Animation může také udržovat kolekci podřízených animací, které lze spustit a synchronizovat. Další informace najdete v tématu Podřízené animace.

Spuštění animace vytvořené pomocí Animation třídy, která může nebo nemusí obsahovat podřízené animace, je dosaženo voláním Commit metody. Tato metoda určuje dobu trvání animace a mimo jiné zpětné volání, které řídí, zda se má animace opakovat.

Poznámka:

Třída AnimationIsEnabled vlastnost, kterou lze prozkoumat a určit, zda byly animace zakázány operačním systémem, například při aktivaci režimu úspory energie.

Animace v Androidu respektují nastavení systémové animace:

  • Pokud jsou animace systému zakázané (funkcemi přístupnosti nebo vývojářskými funkcemi), nové animace se okamžitě přesunou do stavu dokončení.
  • Pokud je režim úspory energie zařízení aktivován, zatímco animace probíhají, animace okamžitě přeskočí do stavu dokončení.
  • Pokud je doba trvání animace zařízení nastavená na nulu (zakázáno), zatímco animace probíhají a verze rozhraní API je 33 nebo vyšší, animace okamžitě přeskočí do stavu dokončení.

Vytvoření animace

Při vytváření objektu Animation se obvykle vyžaduje minimálně tři parametry, jak je znázorněno v následujícím příkladu kódu:

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

V tomto příkladu Scale je animace vlastnosti Image instance definována z hodnoty 1 na hodnotu 2. Animované hodnoty se předají zpětnému volání určenému jako první argument, kde se používá ke změně hodnoty Scale vlastnosti.

Animace se spustí voláním Commit metody:

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

Poznámka:

Metoda Commit nevrací Task objekt. Místo toho se oznámení poskytují prostřednictvím metod zpětného volání.

V metodě jsou zadány Commit následující argumenty:

  • První argument (owner) identifikuje vlastníka animace. Může se jednat o vizuální prvek, na kterém se animace použije, nebo jiný vizuální prvek, například stránku.
  • Druhý argument (name) identifikuje animaci s názvem. Jméno se zkombinuje s vlastníkem a jedinečně identifikuje animaci. Tuto jedinečnou identifikaci pak můžete použít k určení, jestli je animace spuštěná (AnimationIsRunning) nebo jestli ji chcete zrušit (AbortAnimation).
  • Třetí argument (rate) označuje počet milisekund mezi každým voláním metody zpětného volání definovanou v konstruktoru Animation .
  • Čtvrtý argument (length) označuje dobu trvání animace v milisekundách.
  • Pátý argument (Easing) definuje funkci pro usnadnění, která se má použít v animaci. Případně lze funkci easing zadat jako argument konstruktoru Animation . Další informace o usnadnění funkcí najdete v tématu Easing Functions.
  • Šestý argument (finished) je zpětné volání, které se spustí po dokončení animace. Tento zpětný volání přebírá dva argumenty, přičemž první argument označuje konečnou hodnotu a druhý argument je bool nastavený na true hodnotu, pokud byla animace zrušena. Alternativně finished lze zpětné volání zadat jako argument konstruktoru Animation . Pokud jsou však při jedné animaci finished zadány zpětná volání v Animation konstruktoru i Commit metodě, spustí se pouze zpětné volání zadané v Commit metodě.
  • Sedmý argument (repeat) je zpětné volání, které umožňuje opakování animace. Volá se na konci animace a návrat true označuje, že by se animace měla opakovat.

V předchozím příkladu je celkovým efektem vytvoření animace, která pomocí funkce usnadnění zvýší Scale vlastnost Image instance z 1 na 2 sekundy (2000 milisekund Linear ). Pokaždé, když se animace dokončí, Scale její vlastnost se obnoví na hodnotu 1 a animace se opakuje.

Poznámka:

Souběžné animace, které běží nezávisle na sobě, lze vytvořit vytvořením objektu Animation pro každou animaci a následným voláním Commit metody pro každou animaci.

Podřízené animace

Třída Animation také podporuje podřízené animace, což jsou Animation objekty, ke kterým se ostatní Animation objekty přidají jako podřízené objekty. To umožňuje spustit a synchronizovat řadu animací. Následující příklad kódu ukazuje vytváření a spouštění podřízených animací:

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

Příklad kódu lze také napsat výstižněji:

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

V obou příkladech se vytvoří nadřazený Animation objekt, do kterého se pak přidají další Animation objekty. První dva argumenty Add metody určují, kdy začít a dokončit podřízenou animaci. Hodnoty argumentů musí být v rozmezí od 0 do 1 a představují relativní období v rámci nadřazené animace, kterou bude zadaná podřízená animace aktivní. Proto v tomto příkladu scaleUpAnimation bude aktivní pro první polovinu animace, scaleDownAnimation bude aktivní pro druhou polovinu animace a rotateAnimation bude aktivní po celou dobu trvání.

Celkový efekt tohoto příkladu spočívá v tom, že animace probíhá po dobu 4 sekund (4000 milisekund). Animuje scaleUpAnimation Scale vlastnost od 1 do 2, více než 2 sekundy. Potom scaleDownAnimation animuje Scale vlastnost od 2 do 1, více než 2 sekundy. I když se vyskytují obě animace škálování, rotateAnimation animuje Rotation vlastnost od 0 do 360, více než 4 sekundy. Obě animace škálování také používají funkce pro usnadnění. SpringIn Funkce easing způsobí Image počáteční zmenšení instance před zvětšením a SpringOut easing funkce způsobíImage, že se zmenší, než je její skutečná velikost na konci celé animace.

Mezi objektem Animation , který používá podřízené animace, existuje několik rozdílů a mezi objektem, který:

  • Při použití podřízených animací finished zpětné volání u podřízené animace označuje, kdy se podřízená položka dokončila, a finished zpětné volání předané Commit metodě označuje, kdy byla dokončena celá animace.
  • Pokud použijete podřízené animace, vrácení true z zpětného repeat volání metody Commit nezpůsobí opakování animace, ale animace se bude dál spouštět bez nových hodnot.
  • Pokud do Commit metody zahrnete funkci pro usnadnění a funkce pro usnadnění vrátí hodnotu větší než 1, animace se ukončí. Pokud easing funkce vrátí hodnotu menší než 0, hodnota se uchytne na 0. Chcete-li použít funkci easing, která vrací hodnotu menší než 0 nebo větší než 1, musí být určena v jedné z podřízených animací, nikoli v Commit metodě.

Třída Animation také obsahuje WithConcurrent metody, které lze použít k přidání podřízených animací do nadřazeného Animation objektu. Jejich begin hodnoty a finish argumenty ale nejsou omezeny na 0 až 1, ale pouze tato část podřízené animace, která odpovídá rozsahu 0 až 1, bude aktivní. Pokud například WithConcurrent volání metody definuje podřízenou animaci, která cílí na Scale vlastnost od 1 do 6, ale s begin hodnotami finish -2 a 3, begin hodnota -2 odpovídá Scale hodnotě 1 a finish hodnota 3 odpovídá Scale hodnotě 6. Vzhledem k tomu, že hodnoty mimo rozsah 0 a 1 nehrají žádnou roli v animaci, Scale vlastnost bude animované pouze od 3 do 6.

Zrušení animace

Aplikace může vlastní animaci zrušit voláním AbortAnimation metody rozšíření:

this.AbortAnimation ("SimpleAnimation");

Vzhledem k tomu, že animace jsou jedinečně identifikovány kombinací vlastníka animace a názvu animace, musí být zadán vlastník a jméno zadané při spuštění animace, aby se zrušila. Proto tento příklad okamžitě zruší animaci, SimpleAnimation která je vlastněná stránkou.

Vytvoření vlastní animace

Zde uvedené příklady zatím ukázaly animace, které lze stejně dosáhnout metodami ve ViewExtensions třídě. Výhodou Animation třídy však je, že má přístup k metodě zpětného volání, která se spustí při změně animované hodnoty. To umožňuje zpětnému volání implementovat jakoukoli požadovanou animaci. Například následující příklad kódu animuje BackgroundColor vlastnost stránky nastavením na Color hodnoty vytvořené Color.FromHsla metodou, přičemž hodnoty odstínu v rozsahu od 0 do 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 = Colors.Black);

Výsledná animace poskytuje vzhled posouvání pozadí stránky pomocí barev duhy.

Vytvoření vlastní metody rozšíření animace

Rozšiřující metody ve ViewExtensions třídě animují vlastnost z její aktuální hodnoty na zadanou hodnotu. Díky tomu je obtížné vytvořit například animační metodu ColorTo , která se dá použít k animaci barvy z jedné hodnoty do druhé. Důvodem je to, že různé ovládací prvky mají různé vlastnosti typu Color. VisualElement I když třída definuje BackgroundColor vlastnost, není to vždy požadovaná Color vlastnost k animaci.

Řešením tohoto problému je, ColorTo že metoda cílí na konkrétní Color vlastnost. Místo toho je možné ji zapsat metodou zpětného volání, která předá interpolovanou Color hodnotu zpět volajícímu. Kromě toho bude metoda trvat počáteční a koncové Color argumenty.

Tuto ColorTo metodu lze implementovat jako rozšiřující metodu, která metodu Animate AnimationExtensions ve třídě používá k poskytování jeho funkcí. Důvodem je to, že metodu Animate lze použít k cílení vlastností, které nejsou typu double, jak je znázorněno v následujícím příkladu kódu:

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.Red + t * (toColor.Red - fromColor.Red),
                           fromColor.Green + t * (toColor.Green - fromColor.Green),
                           fromColor.Blue + t * (toColor.Blue - fromColor.Blue),
                           fromColor.Alpha + t * (toColor.Alpha - fromColor.Alpha));
        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 vyžaduje transform argument, což je metoda zpětného volání. Vstup do tohoto zpětného volání je vždy v rozsahu double od 0 do 1. V tomto příkladu ColorTo tedy metoda definuje vlastní transformaci Func , která přijímá double hodnotu od 0 do 1 a která vrátí Color hodnotu odpovídající této hodnotě. Hodnota Color je vypočítána interpolací Red, Green, Bluea Alpha hodnotami dvou zadaných Color argumentů. Hodnota Color se pak předá metodě zpětného volání, která se má použít na vlastnost. Tento přístup umožňuje ColorTo metodě animovat jakoukoli zadanou Color vlastnost:

await Task.WhenAll(
  label.ColorTo(Colors.Red, Colors.Blue, c => label.TextColor = c, 5000),
  label.ColorTo(Colors.Blue, Colors.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(Colors.Blue, Colors.Red, c => boxView.Color = c, 4000);

V tomto příkladu ColorTo kódu metoda animuje TextColor a BackgroundColor vlastnosti Label, BackgroundColor vlastnost stránky a Color vlastnost .BoxView