Simplificering af animationer i Flutter med implicit animerede widgets
Animationer er ret nemme at lave i Flutter og en masse kompleksitet kan opnås med en meget mindre indsats end native Android. Dette opnås normalt gennem måder som at definere en Animation + en AnimationController. Men der er indbyggede widgets, der endda reducerer dette og gør animationer så let som blot at ændre værdier!
De komplette eksempler vil blive hostet på min Github-side, der er angivet i slutningen af denne artikel.
En Heroanimation får et element fra én side til at “flyve” til den anden og tilpasser sig automatisk til størrelsen af det samme element på den anden side. Dette gør noget som en liste i en app, der har en detaljeside, så meget mere interessant.
Flutter gør det utrolig nemt at implementere Hero animationer. Det eneste, du skal gøre, er at pakke det element, du vil gøre til en “Hero”, ind i en Hero widget og forsyne det med et tag. Hvis du vil gøre dette i en liste, skal du levere et andet tag for hvert element, som jeg bare normalt indstiller til “hero” + elementets position i listen.
Overstående eksempel har et simpelt kort på den første side med en container med en rød farve.
Hero(
tag: "heroTag",
child: Container(
color: Colors.red,
height: 100.0,
),
),
På detaljesiden er der igen en større container med en rød farve også.
Expanded(
child: Hero(
tag: "heroTag",
child: Container(
color: Colors.red,
),
),
),
Og når jeg skubber det fra den ene side til den anden ved hjælp af
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return new HeroDetailPage();
},
),
);
Det er det!
Den farvede container flyver automatisk og udvider sig til sidstnævntes størrelse.
For et stykke tid siden brugte jeg en masse animationer i en konceptskak-app, som jeg lavede med Flutter.
Her er en artikel, jeg skrev, hvis du vil have et mere detaljeret kig på koden til denne app.
AnimatedCrossFade
En CrossFade er en glidende overgang fra en widget til en anden med en given varighed. Flutter gør dette nemt ved hjælp af en AnimatedCrossFade-widget.
Sådan defineres en AnimatedCrossFade:
AnimatedCrossFade(
firstChild: // Your first element here,
secondChild: // Element after transition,
crossFadeState: // State of the transition,
duration: Duration(milliseconds: 1500),
),
Vi leverer:
- Vidgetten før overgang
firstChild: Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: CircularProgressIndicator(),
),
height: 200.0,
width: 200.0,
),
2. Widgetten efter overgang
secondChild: Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: FlutterLogo(),
),
height: 100.0,
width: 200.0,
),
3. Overgangens tilstand (Om overgangen allerede er sket eller ej)
(Her er firstStateEnabled en boolean, som vi kan ændre for at ændre tilstanden.)
crossFadeState: firstStateEnabled
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
4. Overgangens varighed
duration: Duration(milliseconds: 1500),
Denne mængde kode er nok til at give os ovenstående eksempel. Overgangen udløses simpelthen ved at ændre crossFadeState.
Bemærk: Hvis de to børn er af forskellig størrelse, overgår den automatisk fra den ene størrelse til den anden.
Her er en demo:
AnimatedOpacity
AnimatedOpacity animerer ændringer i opacitet, dvs.dvs. hvor synlig en widget er. En opacitet på 0 gør en widget helt gennemsigtig, mens en opacitet på 1 er fuldt synlig.
AnimatedOpacity er deklareret som:
AnimatedOpacity(
opacity: // Your variable holding opacity value,
duration: // Duration of the transition,
child: FlutterLogo(),
)
I lighed med de sidste par widgets, ændrer du i AnimatedOpacity opaciteten og setState, og den animerer automatisk opacitetsændringen.
I ovenstående eksempel er den erklæret som
AnimatedOpacity(
child: FlutterLogo(size: 100.0,),
opacity: myOpacity,
duration: Duration(seconds: 1),
),
Når der klikkes på knappen, ændrer den blot opaciteten og sætter state.
onPressed: () {
myOpacity = 0.0;
setState(() {});
},