Vlastní animace v Xamarin.Forms
Třída Animation je stavební blok všech Xamarin.Forms animací, s rozšiřujícími metodami ve třídě ViewExtensions vytvářející jeden nebo více animačních objektů. Tento článek ukazuje, jak pomocí třídy Animace vytvářet a rušit animace, synchronizovat více animací a vytvářet vlastní animace, které animují vlastnosti, které nejsou animované existujícími metodami animace.
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 naleznete 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.
Kromě toho třída má IsEnabled
vlastnost, kterou lze prozkoumat a určit, Animation
zda byly animace zakázány operačním systémem, například při aktivaci režimu úspory energie.
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);
Tento kód definuje animaci Scale
vlastnosti Image
instance z hodnoty 1 na hodnotu 2. Animované hodnoty, které jsou odvozeny Xamarin.Forms, je předán zpět zpětné volání zadané jako první argument, kde se používá ke změně hodnoty Scale
vlastnosti.
Animace se spustí voláním Commit
metody, jak je znázorněno v následujícím příkladu kódu:
animation.Commit (this, "SimpleAnimation", 16, 2000, Easing.Linear, (v, c) => image.Scale = 1, () => true);
Všimněte si, že Commit
metoda 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 (vlastník) 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 (název) 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 (sazba) označuje počet milisekund mezi každým voláním metody zpětného volání definovanou v konstruktoru
Animation
. - Čtvrtý argument (délka) označuje dobu trvání animace v milisekundách.
- Pátý argument (easing) definuje funkci 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 (dokončený) 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ý natrue
hodnotu, pokud byla animace zrušena. Případně lze dokončené zpětné volání zadat jako argument konstruktoruAnimation
. Pokud jsou však dokončené zpětné volání zadány vAnimation
konstruktoruCommit
i metodě, spustí se pouze zpětné volání zadané vCommit
metodě. - Sedmý argument (opakovat) 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.
Celkovým efektem je vytvoření animace, která pomocí funkce easing zvýší Scale
vlastnost Image
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, které zahrnují vytvoření objektu Animation
, do kterého jsou přidány další Animation
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, jak je znázorněno v následujícím příkladu kódu:
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 kódu 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 spočívá v tom, že animace trvá více než 4 sekundy (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. Všimněte si, že animace škálování také používají funkce pro usnadnění. Funkce SpringIn
easing způsobí Image
počáteční zmenšení 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í se dokončené zpětné volání v podřízené animaci označuje, kdy se podřízená položka dokončila, a dokončené 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 opakování zpětného volání metodyCommit
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 vCommit
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. Hodnoty argumentů začátek a dokončení ale nejsou omezeny na hodnotu 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 počáteční a koncové hodnoty -2 a 3, počáteční hodnota -2 odpovídá Scale
hodnotě 1 a hodnota dokončení 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 zrušit animaci s voláním AbortAnimation
metody rozšíření, jak je znázorněno v následujícím příkladu kódu:
this.AbortAnimation ("SimpleAnimation");
Všimněte si, že animace jsou jednoznačně identifikovány kombinací vlastníka animace a názvem animace. Proto musí být zadán vlastník a jméno zadané při spuštění animace, aby se animace zrušila. Příklad kódu proto 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 = Color.Default);
Výsledná animace poskytuje vzhled posouvání pozadí stránky pomocí barev duhy.
Další příklady vytváření složitých animací, včetně animace bezierovy křivky, naleznete v kapitole 22 vytváření mobilních aplikací s Xamarin.Forms.
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é, protože:
- Jedinou
Color
vlastností definovanouVisualElement
třídou jeBackgroundColor
, což není vždy požadovanáColor
vlastnost k animaci. - Často je
Color.Default
aktuální hodnotaColor
vlastnosti , která není skutečnou barvou a kterou nelze použít při interpolačních výpočtech.
Ř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.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
vyžaduje argument transformace , 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. Proto metoda definuje vlastní transformaciFunc
, ColorTo
která přijímá double
rozsah od 0 do 1 a která vrací Color
hodnotu odpovídající této hodnotě. Hodnota Color
je vypočítána interpolací R
, G
, B
a A
hodnotami dvou zadaných Color
argumentů. Hodnota Color
se pak předá metodě zpětného volání pro aplikaci do konkrétní vlastnosti.
Tento přístup umožňuje ColorTo
metodě animovat libovolnou Color
vlastnost, jak je znázorněno v následujícím příkladu kódu:
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);
V tomto příkladu ColorTo
kódu metoda animuje TextColor
a BackgroundColor
vlastnosti Label
, BackgroundColor
vlastnost stránky a Color
vlastnost .BoxView