Apps mit Flutter animieren
Veröffentlicht: 2022-03-10Apps für jede Plattform werden gelobt, wenn sie intuitiv und gut aussehend sind und ein angenehmes Feedback zu Benutzerinteraktionen geben. Animation ist eine der Möglichkeiten, genau das zu tun.
Flutter, ein plattformübergreifendes Framework, ist in den letzten zwei Jahren um Web- und Desktop-Unterstützung gereift. Es hat sich den Ruf erworben, dass damit entwickelte Apps reibungslos und gut aussehend sind. Mit seiner umfangreichen Animationsunterstützung, der deklarativen Schreibweise der Benutzeroberfläche, „Hot Reload“ und anderen Funktionen ist es jetzt ein vollständiges plattformübergreifendes Framework.
Wenn Sie mit Flutter beginnen und eine unkonventionelle Art des Hinzufügens von Animationen lernen möchten, sind Sie hier genau richtig: Wir werden das Reich der Animations- und Bewegungs-Widgets erkunden, eine implizite Art, Animationen hinzuzufügen.
Flutter basiert auf dem Konzept von Widgets. Jede visuelle Komponente einer App ist ein Widget – stellen Sie sie sich als Ansichten in Android vor. Flutter bietet Animationsunterstützung mit einer Animationsklasse, einem „AnimationController“-Objekt für die Verwaltung und „Tween“ zum Interpolieren des Datenbereichs. Diese drei Komponenten arbeiten zusammen, um eine reibungslose Animation bereitzustellen. Da dies eine manuelle Erstellung und Verwaltung von Animationen erfordert, ist dies als explizite Art der Animation bekannt.
Lassen Sie mich Ihnen nun Animations- und Bewegungs-Widgets vorstellen. Flutter bietet zahlreiche Widgets, die von Natur aus Animationen unterstützen. Es ist nicht erforderlich, ein Animationsobjekt oder einen Controller zu erstellen, da die gesamte Animation von dieser Kategorie von Widgets verwaltet wird. Wählen Sie einfach das entsprechende Widget für die erforderliche Animation aus und übergeben Sie die Eigenschaftswerte des zu animierenden Widgets. Diese Technik ist eine implizite Art der Animation.

Das obige Diagramm zeigt grob die Animationshierarchie in Flutter, wie sowohl explizite als auch implizite Animation unterstützt werden.
Einige der in diesem Artikel behandelten animierten Widgets sind:
-
AnimatedOpacity
-
AnimatedCrossFade
-
AnimatedAlign
-
AnimatedPadding
-
AnimatedSize
-
AnimatedPositioned
.
Flutter bietet nicht nur vordefinierte animierte Widgets, sondern auch ein generisches Widget namens AnimatedWidget
, mit dem benutzerdefinierte implizit animierte Widgets erstellt werden können. Wie aus dem Namen hervorgeht, gehören diese Widgets zur Kategorie der Animations- und Bewegungs-Widgets und haben daher einige gemeinsame Eigenschaften, die es uns ermöglichen, Animationen viel flüssiger und besser aussehend zu machen.
Lassen Sie mich diese gemeinsamen Eigenschaften jetzt erklären, da sie später in allen Beispielen verwendet werden.
-
duration
Die Dauer, über die die Parameter animiert werden sollen. -
reverseDuration
Die Dauer der umgekehrten Animation. -
curve
Die beim Animieren der Parameter anzuwendende Kurve. Die interpolierten Werte können einer linearen Verteilung oder, falls angegeben, einer Kurve entnommen werden.
Lassen Sie uns die Reise beginnen, indem wir eine einfache App erstellen, die wir „Quoted“ nennen. Bei jedem Start der App wird ein zufälliges Zitat angezeigt. Zwei Dinge sind zu beachten: Erstens werden alle diese Zitate in der Anwendung fest codiert; und zweitens werden keine Benutzerdaten gespeichert.
Hinweis : Alle Dateien für diese Beispiele finden Sie auf GitHub.
Einstieg
Flutter sollte installiert sein und Sie müssen sich mit dem grundlegenden Ablauf vertraut machen, bevor Sie fortfahren. Ein guter Ausgangspunkt ist „Using Google's Flutter For Truely Cross-Platform Mobile Development“.
Erstellen Sie ein neues Flutter-Projekt in Android Studio.

Dadurch wird ein neuer Projektassistent geöffnet, in dem Sie die Projektgrundlagen konfigurieren können.

Auf dem Bildschirm zur Auswahl des Projekttyps gibt es verschiedene Arten von Flutter-Projekten, die jeweils auf ein bestimmtes Szenario ausgerichtet sind. Wählen Sie für dieses Tutorial Flutter-Anwendung und drücken Sie auf Weiter .
Sie müssen nun einige projektspezifische Informationen eingeben: Projektname und -pfad, Unternehmensdomäne usw. Schauen Sie sich das Bild unten an.

Fügen Sie den Projektnamen, den Flutter-SDK-Pfad, den Projektspeicherort und eine optionale Projektbeschreibung hinzu. Drücken Sie Weiter .

Jede Anwendung (ob Android oder iOS) erfordert einen eindeutigen Paketnamen. Normalerweise verwenden Sie die Rückseite Ihrer Website-Domain; B. com.google oder com.yahoo. Drücken Sie Finish , um eine funktionierende Flutter-Anwendung zu generieren.

Sobald das Projekt generiert ist, sollten Sie den oben gezeigten Bildschirm sehen. Öffnen Sie die main.dart -Datei (im Screenshot hervorgehoben). Dies ist die Hauptanwendungsdatei. Das Beispielprojekt ist in sich abgeschlossen und kann ohne Änderungen direkt auf einem Emulator oder einem physischen Gerät ausgeführt werden.
Ersetzen Sie den Inhalt der Datei main.dart durch das folgende Code-Snippet:
import 'package:animated_widgets/FirstPage.dart'; import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Animated Widgets', debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.blue, accentColor: Colors.redAccent, ), home: FirstPage(), ); } }
Dieser Code bereinigt die main.dart -Datei, indem er einfach einfache Informationen hinzufügt, die für die Erstellung einer neuen App relevant sind. Die Klasse MyApp gibt ein Objekt zurück: ein MaterialApp
-Widget, das die Grundstruktur zum Erstellen von Apps gemäß Material Design bereitstellt. Um den Code strukturierter zu gestalten, erstellen Sie zwei neue dart-Dateien im lib -Ordner: FirstPage.dart und Quotes.dart .

FirstPage.dart enthält den gesamten Code, der für alle visuellen Elemente (Widgets) verantwortlich ist, die für unsere Quoted-App erforderlich sind. Die gesamte Animation wird in dieser Datei behandelt.
Hinweis : Später in diesem Artikel werden alle Codeausschnitte für jedes animierte Widget dieser Datei als untergeordnete Elemente des Scaffold-Widgets hinzugefügt. Für weitere Informationen könnte dieses Beispiel auf GitHub nützlich sein.
Beginnen Sie mit dem Hinzufügen des folgenden Codes zu FirstPage.dart . Dies ist der Teilcode, dem später andere Dinge hinzugefügt werden.
import 'dart:math'; import 'package:animated_widgets/Quotes.dart'; import 'package:flutter/material.dart'; class FirstPage extends StatefulWidget { @override State createState() { return FirstPageState(); } } class FirstPageState extends State with TickerProviderStateMixin { bool showNextButton = false; bool showNameLabel = false; bool alignTop = false; bool increaseLeftPadding = false; bool showGreetings = false; bool showQuoteCard = false; String name = ''; double screenWidth; double screenHeight; String quote; @override void initState() { super.initState(); Random random = new Random(); int quoteIndex = random.nextInt(Quotes.quotesArray.length); quote = Quotes.quotesArray[quoteIndex]; } @override Widget build(BuildContext context) { screenWidth = MediaQuery.of(context).size.width; screenHeight = MediaQuery.of(context).size.height; return Scaffold( appBar: _getAppBar(), body: Stack( children: [ // All other children will be added here. // In this article, all the children widgets are contained // in their own separate methods. // Just method calls should be added here for the respective child. ], ), ); } }
import 'dart:math'; import 'package:animated_widgets/Quotes.dart'; import 'package:flutter/material.dart'; class FirstPage extends StatefulWidget { @override State createState() { return FirstPageState(); } } class FirstPageState extends State with TickerProviderStateMixin { bool showNextButton = false; bool showNameLabel = false; bool alignTop = false; bool increaseLeftPadding = false; bool showGreetings = false; bool showQuoteCard = false; String name = ''; double screenWidth; double screenHeight; String quote; @override void initState() { super.initState(); Random random = new Random(); int quoteIndex = random.nextInt(Quotes.quotesArray.length); quote = Quotes.quotesArray[quoteIndex]; } @override Widget build(BuildContext context) { screenWidth = MediaQuery.of(context).size.width; screenHeight = MediaQuery.of(context).size.height; return Scaffold( appBar: _getAppBar(), body: Stack( children: [ // All other children will be added here. // In this article, all the children widgets are contained // in their own separate methods. // Just method calls should be added here for the respective child. ], ), ); } }
import 'dart:math'; import 'package:animated_widgets/Quotes.dart'; import 'package:flutter/material.dart'; class FirstPage extends StatefulWidget { @override State createState() { return FirstPageState(); } } class FirstPageState extends State with TickerProviderStateMixin { bool showNextButton = false; bool showNameLabel = false; bool alignTop = false; bool increaseLeftPadding = false; bool showGreetings = false; bool showQuoteCard = false; String name = ''; double screenWidth; double screenHeight; String quote; @override void initState() { super.initState(); Random random = new Random(); int quoteIndex = random.nextInt(Quotes.quotesArray.length); quote = Quotes.quotesArray[quoteIndex]; } @override Widget build(BuildContext context) { screenWidth = MediaQuery.of(context).size.width; screenHeight = MediaQuery.of(context).size.height; return Scaffold( appBar: _getAppBar(), body: Stack( children: [ // All other children will be added here. // In this article, all the children widgets are contained // in their own separate methods. // Just method calls should be added here for the respective child. ], ), ); } }
import 'dart:math'; import 'package:animated_widgets/Quotes.dart'; import 'package:flutter/material.dart'; class FirstPage extends StatefulWidget { @override State createState() { return FirstPageState(); } } class FirstPageState extends State with TickerProviderStateMixin { bool showNextButton = false; bool showNameLabel = false; bool alignTop = false; bool increaseLeftPadding = false; bool showGreetings = false; bool showQuoteCard = false; String name = ''; double screenWidth; double screenHeight; String quote; @override void initState() { super.initState(); Random random = new Random(); int quoteIndex = random.nextInt(Quotes.quotesArray.length); quote = Quotes.quotesArray[quoteIndex]; } @override Widget build(BuildContext context) { screenWidth = MediaQuery.of(context).size.width; screenHeight = MediaQuery.of(context).size.height; return Scaffold( appBar: _getAppBar(), body: Stack( children: [ // All other children will be added here. // In this article, all the children widgets are contained // in their own separate methods. // Just method calls should be added here for the respective child. ], ), ); } }

Die Datei Quotes.dart enthält eine Liste aller hartcodierten Zitate. Hierbei ist zu beachten, dass die Liste ein statisches Objekt ist. Das bedeutet, dass es an anderen Stellen verwendet werden kann, ohne ein neues Objekt der Klasse Quotes zu erstellen. Dies ist beabsichtigt, da die obige Liste lediglich als Hilfsprogramm dient.
Fügen Sie dieser Datei den folgenden Code hinzu:
class Quotes { static const quotesArray = [ "Good, better, best. Never let it rest. 'Til your good is better and your better is best", "It does not matter how slowly you go as long as you do not stop.", "Only I can change my life. No one can do it for me." ]; }
Das Projektskelett ist jetzt fertig, also lassen Sie uns Quoted ein wenig weiter ausarbeiten.

AnimatedOpacity
Um der App eine persönliche Note zu verleihen, wäre es schön, den Namen des Benutzers zu kennen, also lassen Sie uns danach fragen und einen Weiter-Button anzeigen. Bis der Benutzer seinen Namen eingibt, ist diese Schaltfläche ausgeblendet und wird elegant angezeigt, wenn ein Name angegeben wird. Wir brauchen eine Art Sichtbarkeitsanimation für die Schaltfläche, aber gibt es dafür ein Widget? Ja da ist.
Geben Sie AnimatedOpacity
. Dieses Widget baut auf dem Deckkraft-Widget auf, indem es Unterstützung für implizite Animationen hinzufügt. Wie verwenden wir es? Erinnern Sie sich an unser Szenario: Wir müssen eine Schaltfläche „Weiter“ mit animierter Sichtbarkeit anzeigen. Wir packen das Schaltflächen-Widget in das AnimatedOpacity
-Widget, geben einige geeignete Werte ein und fügen eine Bedingung hinzu, um die Animation auszulösen – und Flutter erledigt den Rest.
_getAnimatedOpacityButton() { return AnimatedOpacity( duration: Duration(seconds: 1), reverseDuration: Duration(seconds: 1), curve: Curves.easeInOut, opacity: showNextButton ? 1 : 0, child: _getButton(), ); }

Das AnimatedOpacity
-Widget hat zwei obligatorische Eigenschaften:
-
opacity
Ein Wert von 1 bedeutet vollständig sichtbar; 0 (Null) bedeutet ausgeblendet. Während der Animation interpoliert Flutter Werte zwischen diesen beiden Extremen. Sie können sehen, wie eine Bedingung platziert wird, um die Sichtbarkeit zu ändern und so eine Animation auszulösen. -
child
Das untergeordnete Widget, dessen Sichtbarkeit animiert wird.
Sie sollten jetzt verstehen, wie einfach es ist, Sichtbarkeitsanimationen mit dem impliziten Widget hinzuzufügen. Und alle diese Widgets folgen den gleichen Richtlinien und sind einfach zu bedienen. Kommen wir zum nächsten.
AnimatedCrossFade
Wir haben den Namen des Benutzers, aber das Widget wartet noch auf Eingaben. Wenn der Benutzer im vorherigen Schritt seinen Namen eingibt, zeigen wir die nächste Schaltfläche an. Wenn der Benutzer jetzt auf die Schaltfläche drückt, möchte ich die Annahme von Eingaben beenden und den eingegebenen Namen anzeigen. Es gibt natürlich viele Möglichkeiten, dies zu tun, aber vielleicht können wir das Eingabe-Widget ausblenden und ein nicht bearbeitbares Text-Widget anzeigen. Probieren wir es mit dem AnimatedCrossFade
-Widget aus.
Dieses Widget erfordert zwei untergeordnete Elemente, da das Widget basierend auf einer bestimmten Bedingung zwischen ihnen überblendet. Eine wichtige Sache, die Sie bei der Verwendung dieses Widgets beachten sollten, ist, dass beide Kinder die gleiche Breite haben sollten. Wenn die Höhe unterschiedlich ist, wird das größere Widget von unten abgeschnitten. In diesem Szenario werden zwei Widgets als Kinder verwendet: input und label.
_getAnimatedCrossfade() { return AnimatedCrossFade( duration: Duration(seconds: 1), alignment: Alignment.center, reverseDuration: Duration(seconds: 1), firstChild: _getNameInputWidget(), firstCurve: Curves.easeInOut, secondChild: _getNameLabelWidget(), secondCurve: Curves.easeInOut, crossFadeState: showNameLabel ? CrossFadeState.showSecond : CrossFadeState.showFirst, ); }

Dieses Widget erfordert einen anderen Satz obligatorischer Parameter:
-
crossFadeState
Dieser Zustand bestimmt, welches Kind gezeigt werden soll. -
firstChild
Gibt das erste Kind für dieses Widget an. -
secondChild
Gibt das zweite Kind an.
AnimatedAlign
An diesem Punkt befindet sich das Namensschild in der Mitte des Bildschirms. Oben sieht es viel besser aus, da wir die Mitte des Bildschirms benötigen, um Zitate anzuzeigen. Einfach ausgedrückt, die Ausrichtung des Namensschild-Widgets sollte von der Mitte nach oben geändert werden. Und wäre es nicht schön, diese Ausrichtungsänderung zusammen mit der vorherigen Überblendungsanimation zu animieren? Machen wir das.
Wie immer können mehrere Techniken verwendet werden, um dies zu erreichen. Da das Namensbeschriftungs-Widget bereits zentriert ausgerichtet ist, wäre das Animieren seiner Ausrichtung viel einfacher als das Manipulieren der oberen und linken Werte des Widgets. Das AnimatedAlign
-Widget ist perfekt für diesen Job.
Um diese Animation zu initiieren, ist ein Trigger erforderlich. Der einzige Zweck dieses Widgets besteht darin, die Ausrichtungsänderung zu animieren, daher hat es nur wenige Eigenschaften: Fügen Sie ein untergeordnetes Element hinzu, legen Sie seine Ausrichtung fest, lösen Sie die Ausrichtungsänderung aus, und das war's.
_getAnimatedAlignWidget() { return AnimatedAlign( duration: Duration(seconds: 1), curve: Curves.easeInOut, alignment: alignTop ? Alignment.topLeft : Alignment.center, child: _getAnimatedCrossfade(), ); }

Es hat nur zwei obligatorische Eigenschaften:
- Kind:
Das untergeordnete Element, dessen Ausrichtung geändert wird. - Ausrichtung:
Erforderlicher Ausrichtungswert.
Dieses Widget ist wirklich einfach, aber die Ergebnisse sind elegant. Außerdem haben wir gesehen, wie einfach wir zwei verschiedene animierte Widgets verwenden können, um eine komplexere Animation zu erstellen. Das ist das Schöne an animierten Widgets.
AnimatedPadding
Jetzt haben wir oben den Namen des Benutzers, der ohne großen Aufwand flüssig animiert wird, indem verschiedene Arten von animierten Widgets verwendet werden. Lassen Sie uns vor dem Namen eine Begrüßung „Hallo“ hinzufügen. Wenn Sie oben ein Text-Widget mit dem Wert „Hi“ hinzufügen, überlappt es das Begrüßungstext-Widget und sieht aus wie im Bild unten.

Was wäre, wenn das Namenstext-Widget auf der linken Seite etwas aufgefüllt wäre? Das Erhöhen der linken Polsterung wird definitiv funktionieren, aber warten Sie: Können wir die Polsterung mit einer Animation erhöhen? Ja, und genau das macht AnimatedPadding
. Um das alles viel besser aussehen zu lassen, lassen wir das Begrüßungstext-Widget einblenden und gleichzeitig die Auffüllung des Namenstext-Widgets erhöhen.
_getAnimatedPaddingWidget() { return AnimatedPadding( duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn, padding: increaseLeftPadding ? EdgeInsets.only(left: 28.0) : EdgeInsets.only(left: 0), child: _getAnimatedCrossfade(), ); }
Da die obige Animation erst nach Abschluss der vorherigen animierten Ausrichtung erfolgen soll, müssen wir das Auslösen dieser Animation verzögern. Um kurz vom Thema abzuschweifen, ist dies ein guter Moment, um über einen beliebten Mechanismus zum Hinzufügen von Verzögerungen zu sprechen. Flutter bietet mehrere solcher Techniken, aber der Future.delayed-Konstruktor ist einer der einfacheren, saubereren und besser lesbaren Ansätze. Um beispielsweise einen Code nach 1 Sekunde auszuführen:
Future.delayed(Duration(seconds: 1), (){ sum = a + b; // This sum will be calculated after 1 second. print(sum); });
Da die Verzögerungsdauer bereits bekannt ist (aus früheren Animationsdauern berechnet), kann die Animation nach diesem Intervall ausgelöst werden.
// Showing “Hi” after 1 second - greetings visibility trigger. _showGreetings() { Future.delayed(Duration(seconds: 1), () { setState(() { showGreetings = true; }); }); } // Increasing the padding for name label widget after 1 second - increase padding trigger. _increaseLeftPadding() { Future.delayed(Duration(seconds: 1), () { setState(() { increaseLeftPadding = true; }); }); }

Dieses Widget hat nur zwei obligatorische Eigenschaften:
-
child
Das untergeordnete Element in diesem Widget, auf das Padding angewendet wird. -
padding
Die Menge an Speicherplatz, die hinzugefügt werden soll.
AnimatedSize
Heutzutage umfasst jede App mit einer Art Animation das Vergrößern oder Verkleinern von visuellen Komponenten, um die Aufmerksamkeit des Benutzers zu erregen (allgemein als Skalierungsanimation bezeichnet). Warum nicht die gleiche Technik hier verwenden? Wir können dem Benutzer ein Motivationszitat zeigen, das von der Mitte des Bildschirms heranzoomt. Lassen Sie mich Ihnen das AnimatedSize
-Widget vorstellen, das die Zoom-In- und Zoom-Out-Effekte aktiviert, die durch Ändern der Größe seines untergeordneten Elements gesteuert werden.
Dieses Widget unterscheidet sich ein wenig von den anderen, wenn es um die erforderlichen Parameter geht. Wir brauchen das, was Flutter einen „Ticker“ nennt. Flutter verfügt über eine Methode, um Objekte darüber zu informieren, wann immer ein neues Frame-Ereignis ausgelöst wird. Es kann als etwas betrachtet werden, das ein Signal sendet, das sagt: „Mach es jetzt! … Mach es jetzt! … Mach es jetzt! …“
Das AnimatedSize
-Widget erfordert eine Eigenschaft – vsync – die einen Ticker-Anbieter akzeptiert. Der einfachste Weg, einen Ticker-Anbieter zu erhalten, besteht darin, der Klasse ein Mixin hinzuzufügen. Es gibt zwei grundlegende Implementierungen von Tickeranbietern: SingleTickerProviderStateMixin
, das einen einzelnen Ticker bereitstellt; und TickerProviderStateMixin
, das mehrere bereitstellt.
Die Standardimplementierung eines Tickers wird verwendet, um die Frames einer Animation zu markieren. In diesem Fall wird letzteres verwendet. Mehr über Mixins.
// Helper method to create quotes card widget. _getQuoteCardWidget() { return Card( color: Colors.green, elevation: 8.0, child: _getAnimatedSizeWidget(), ); } // Helper method to create animated size widget and set its properties. _getAnimatedSizeWidget() { return AnimatedSize( duration: Duration(seconds: 1), curve: Curves.easeInOut, vsync: this, child: _getQuoteContainer(), ); } // Helper method to create the quotes container widget with different sizes. _getQuoteContainer() { return Container( height: showQuoteCard ? 100 : 0, width: showQuoteCard ? screenWidth - 32 : 0, child: Center( child: Padding( padding: EdgeInsets.symmetric(horizontal: 16), child: Text(quote, style: TextStyle(color: Colors.white, fontWeight: FontWeight.w400, fontSize: 14),), ), ), ); } // Trigger used to show the quote card widget. _showQuote() { Future.delayed(Duration(seconds: 2), () { setState(() { showQuoteCard = true; }); }); }

Obligatorische Eigenschaften für dieses Widget:
-
vsync
Der erforderliche Tickeranbieter, um Animations- und Frameänderungen zu koordinieren.< -
child
Das Kind, dessen Größe sich ändert, wird animiert.
Die Zoom-in- und Zoom-out-Animation ist jetzt leicht zu bändigen.
AnimatedPositioned
Toll! Die Anführungszeichen zoomen von der Mitte heran, um die Aufmerksamkeit des Benutzers zu erregen. Was ist, wenn es beim Vergrößern von unten nach oben rutscht? Lass es uns versuchen. Diese Bewegung beinhaltet das Spielen mit der Position des Zitat-Widgets und das Animieren der Änderungen der Positionseigenschaften. AnimatedPositioned
ist der perfekte Kandidat.
Dieses Widget wechselt automatisch die Position des Kindes über einen bestimmten Zeitraum, wenn sich die angegebene Position ändert. Ein Hinweis: Es funktioniert nur, wenn das übergeordnete Widget ein „Stack“ ist. Dieses Widget ist ziemlich einfach und unkompliziert zu bedienen. Mal sehen.
// Helper method to create the animated positioned widget. // With position changes based on “showQuoteCard” flag. _getAnimatedPositionWidget() { return AnimatedPositioned( duration: Duration(seconds: 1), curve: Curves.easeInOut, child: _getQuoteCardWidget(), top: showQuoteCard ? screenHeight/2 - 100 : screenHeight, left: !showQuoteCard ? screenWidth/2 : 12, ); }

Dieses Widget hat nur eine obligatorische Eigenschaft:
-
child
Das Widget, dessen Position geändert wird.
Wenn nicht erwartet wird, dass sich die Größe des untergeordneten Elements zusammen mit seiner Position ändert, wäre SlideTransition
eine leistungsfähigere Alternative zu diesem Widget.
Hier ist unsere komplette Animation:

Fazit
Animationen sind ein wesentlicher Bestandteil der Benutzererfahrung. Statische Apps oder Apps mit ruckeliger Animation verringern nicht nur die Benutzerbindung, sondern auch den Ruf eines Entwicklers, Ergebnisse zu liefern.
Heutzutage haben die beliebtesten Apps eine Art subtiler Animation, um die Benutzer zu erfreuen. Animiertes Feedback zu Benutzeranfragen kann sie auch dazu anregen, mehr zu erkunden. Flutter bietet viele Funktionen für die plattformübergreifende Entwicklung, einschließlich umfassender Unterstützung für reibungslose und reaktionsschnelle Animationen.
Flutter hat eine großartige Plug-In-Unterstützung, die es uns ermöglicht, Animationen von anderen Entwicklern zu verwenden. Jetzt, da es mit so viel Liebe von der Community zu Version 1.9 gereift ist, wird Flutter in Zukunft bestimmt noch besser werden. Ich würde sagen, jetzt ist eine großartige Zeit, um Flutter zu lernen!
Weitere Ressourcen
- „Animations- und Bewegungs-Widgets“, Flutter Docs
- „Einführung in Animationen“, Flutter Docs
- Flutter-Codelabs
Anmerkung des Herausgebers : Ein riesiges Dankeschön an Ahmad Awais für seine Hilfe bei der Überprüfung dieses Artikels.