Implicit animerede widgets i Flutter

Simplificering af animationer i Flutter med implicit animerede widgets

Deven Joshi
Deven Joshi

Follow

12. okt, 2018 – 5 min read

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 AnimatedContainer i Flutter

En AnimatedContainer overgår automatisk til de definerede værdier (farver, størrelser osv.) i stedet for blot at skifte øjeblikkeligt til dem. GIF’en ovenfor er et eksempel på en AnimatedContainer.

En AnimatedContainer er defineret som:

var myColor = Colors.blue;
var myHeight = 100.0;
var myWidth = 100.0;AnimatedContainer(
duration: Duration(seconds: 1),
color: myColor,
height: myHeight,
width: myWidth,
),

I normale tilfælde ville du definere en controller og en Tween<double> og en ColorTween for at opnå animationen i GIF’en ovenfor. Men med AnimatedContainer skal du blot:

  1. Sæt en varighed for animationen
 duration: Duration(seconds: 1),

2. Skift værdier (Skift farve og størrelse til dine værdier)

 myColor = Colors.green;
myHeight = MediaQuery.of(context).size.height;
myWidth = MediaQuery.of(context).size.width;

3. SetState()

 setState(() {});

Ingen controllere. Ingen Tweens.

Det øjeblik du ændrer værdierne for myColor, my Height eller myWidth og setState(), overgår containeren automatisk til værdierne i stedet for at ændre direkte til den pågældende værdi.

onPressed: () {
myColor = Colors.green;
myHeight = MediaQuery.of(context).size.height;
myWidth = MediaQuery.of(context).size.width;
setState(() {});
}

I begyndelsen var myColor indstillet til Colors.blue. Når vi ændrer den til Colors.green og setState for at genopbygge den, overgår den fra blå til grøn, uden at der bruges nogen Tweens. (Bemærk: Tweens bruges implicit, men behøver ikke at være brugerdefineret.)

Fra hvad jeg har set, synes mange udviklere ikke at være opmærksomme på disse implicit animerede widgets og spilder tid, når det ikke er nødvendigt. Der vil naturligvis være tilfælde, hvor du måske ønsker en anden form for adfærd, men de fleste gange gør AnimatedContainer jobbet.

Heroanimationer

Heroanimationer i Flutter

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

AnimatedCrossFades i Flutter

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:

  1. 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(() {});
},

Skriv en kommentar