Flattern - Animation

Animation ist ein komplexer Vorgang in jeder mobilen Anwendung. Trotz seiner Komplexität verbessert Animation die Benutzererfahrung auf ein neues Niveau und bietet eine umfassende Benutzerinteraktion. Animation wird aufgrund ihres Reichtums zu einem integralen Bestandteil moderner mobiler Anwendungen. Das Flutter-Framework erkennt die Bedeutung der Animation und bietet ein einfaches und intuitives Framework für die Entwicklung aller Arten von Animationen.

Einführung

Animation ist ein Prozess, bei dem eine Reihe von Bildern / Bildern in einer bestimmten Reihenfolge innerhalb einer bestimmten Dauer angezeigt wird, um eine Illusion von Bewegung zu erzeugen. Die wichtigsten Aspekte der Animation sind:

  • Die Animation hat zwei unterschiedliche Werte: Startwert und Endwert. Die Animation beginnt von Anfang Wert und geht durch eine Reihe von Zwischenwerten und schließlich bei Endwerte endet. Um beispielsweise ein Widget zum Ausblenden zu animieren, ist der Anfangswert die volle Deckkraft und der Endwert die Deckkraft Null.

  • Die Zwischenwerte können linearer oder nichtlinearer (Kurve) Natur sein und können konfiguriert werden. Verstehen Sie, dass die Animation so funktioniert, wie sie konfiguriert ist. Jede Konfiguration verleiht der Animation ein anderes Gefühl. Das Ausblenden eines Widgets ist beispielsweise linear, während das Abprallen eines Balls nicht linear ist.

  • Die Dauer des Animationsprozesses beeinflusst die Geschwindigkeit (Langsamkeit oder Schnelligkeit) der Animation.

  • Die Möglichkeit, den Animationsprozess zu steuern, z. B. das Starten der Animation, das Stoppen der Animation, das Wiederholen der Animation, um die Anzahl festzulegen, das Umkehren des Animationsprozesses usw.

  • In Flutter führt das Animationssystem keine echte Animation aus. Stattdessen werden nur die Werte bereitgestellt, die für jedes Bild zum Rendern der Bilder erforderlich sind.

Animationsbasierte Klassen

Das Flatter-Animationssystem basiert auf Animationsobjekten. Die Kernanimationsklassen und ihre Verwendung sind wie folgt:

Animation

Erzeugt interpolierte Werte zwischen zwei Zahlen über eine bestimmte Dauer. Die häufigsten Animationsklassen sind -

  • Animation<double> - Werte zwischen zwei Dezimalzahlen interpolieren

  • Animation<Color> - Interpolieren Sie Farben zwischen zwei Farben

  • Animation<Size> - Interpolieren Sie Größen zwischen zwei Größen

  • AnimationController- Spezielles Animationsobjekt zur Steuerung der Animation selbst. Es generiert neue Werte, wenn die Anwendung für einen neuen Frame bereit ist. Es unterstützt lineare Animationen und der Wert beginnt bei 0,0 bis 1,0

controller = AnimationController(duration: const Duration(seconds: 2), vsync: this);

Hier steuert der Controller die Animation und die Option Dauer steuert die Dauer des Animationsprozesses. vsync ist eine spezielle Option zur Optimierung der in der Animation verwendeten Ressource.

CurvedAnimation

Ähnlich wie AnimationController, unterstützt jedoch nichtlineare Animationen. CurvedAnimation kann zusammen mit dem Animationsobjekt wie folgt verwendet werden:

controller = AnimationController(duration: const Duration(seconds: 2), vsync: this); 
animation = CurvedAnimation(parent: controller, curve: Curves.easeIn)

Tween <T>

Abgeleitet von Animatable <T> und zum Generieren von Zahlen zwischen zwei beliebigen Zahlen außer 0 und 1. Es kann zusammen mit dem Animationsobjekt verwendet werden, indem die Animationsmethode verwendet und das eigentliche Animationsobjekt übergeben wird.

AnimationController controller = AnimationController( 
   duration: const Duration(milliseconds: 1000), 
vsync: this); Animation<int> customTween = IntTween(
   begin: 0, end: 255).animate(controller);
  • Tween kann auch zusammen mit CurvedAnimation wie folgt verwendet werden -

AnimationController controller = AnimationController(
   duration: const Duration(milliseconds: 500), vsync: this); 
final Animation curve = CurvedAnimation(parent: controller, curve: Curves.easeOut); 
Animation<int> customTween = IntTween(begin: 0, end: 255).animate(curve);

Hier ist der Controller der eigentliche Animations-Controller. Die Kurve gibt den Typ der Nichtlinearität an und das customTween bietet einen benutzerdefinierten Bereich von 0 bis 255.

Arbeitsablauf der Flatteranimation

Der Arbeitsablauf der Animation ist wie folgt:

  • Definieren und starten Sie den Animations-Controller im initState des StatefulWidget.

AnimationController(duration: const Duration(seconds: 2), vsync: this); 
animation = Tween<double>(begin: 0, end: 300).animate(controller); 
controller.forward();
  • Fügen Sie einen animationsbasierten Listener und addListener hinzu, um den Status des Widgets zu ändern.

animation = Tween<double>(begin: 0, end: 300).animate(controller) ..addListener(() {
   setState(() { 
      // The state that has changed here is the animation object’s value. 
   }); 
});
  • Mit eingebauten Widgets, AnimatedWidget und AnimatedBuilder können Sie diesen Vorgang überspringen. Beide Widgets akzeptieren Animationsobjekte und erhalten aktuelle Werte, die für die Animation erforderlich sind.

  • Rufen Sie die Animationswerte während des Erstellungsprozesses des Widgets ab und wenden Sie sie anstelle des ursprünglichen Werts auf Breite, Höhe oder eine relevante Eigenschaft an.

child: Container( 
   height: animation.value, 
   width: animation.value, 
   child: <Widget>, 
)

Arbeitsanwendung

Schreiben wir eine einfache animationsbasierte Anwendung, um das Konzept der Animation im Flutter-Framework zu verstehen.

  • Erstellen Sie eine neue Flutter- Anwendung in Android Studio, product_animation_app.

  • Kopieren Sie den Assets-Ordner von product_nav_app nach product_animation_app und fügen Sie Assets in die Datei pubspec.yaml ein.

flutter: 
   assets: 
   - assets/appimages/floppy.png 
   - assets/appimages/iphone.png 
   - assets/appimages/laptop.png 
   - assets/appimages/pendrive.png 
   - assets/appimages/pixel.png 
   - assets/appimages/tablet.png
  • Entfernen Sie den Standardstartcode (main.dart).

  • Import und grundlegende Hauptfunktion hinzufügen.

import 'package:flutter/material.dart'; 
void main() => runApp(MyApp());
  • Erstellen Sie das von StatefulWidgtet abgeleitete MyApp-Widget.

class MyApp extends StatefulWidget { 
   _MyAppState createState() => _MyAppState(); 
}
  • Erstellen Sie das Widget _MyAppState, implementieren Sie initState und entsorgen Sie es zusätzlich zur Standarderstellungsmethode.

class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin { 
   Animation<double> animation; 
   AnimationController controller; 
   @override void initState() {
      super.initState(); 
      controller = AnimationController(
         duration: const Duration(seconds: 10), vsync: this
      ); 
      animation = Tween<double>(begin: 0.0, end: 1.0).animate(controller); 
      controller.forward(); 
   } 
   // This widget is the root of your application. 
   @override 
   Widget build(BuildContext context) {
      controller.forward(); 
      return MaterialApp(
         title: 'Flutter Demo',
         theme: ThemeData(primarySwatch: Colors.blue,), 
         home: MyHomePage(title: 'Product layout demo home page', animation: animation,)
      ); 
   } 
   @override 
   void dispose() {
      controller.dispose();
      super.dispose();
   }
}

Hier,

  • In der initState-Methode haben wir ein Animations-Controller-Objekt (Controller) und ein Animationsobjekt (Animation) erstellt und die Animation mit controller.forward gestartet.

  • Bei der Entsorgungsmethode haben wir das Animations-Controller-Objekt (Controller) entsorgt.

  • Senden Sie in der Erstellungsmethode eine Animation über den Konstruktor an das MyHomePage-Widget. Jetzt kann das MyHomePage-Widget das Animationsobjekt verwenden, um seinen Inhalt zu animieren.

  • Fügen Sie nun das ProductBox-Widget hinzu

class ProductBox extends StatelessWidget {
   ProductBox({Key key, this.name, this.description, this.price, this.image})
      : super(key: key);
   final String name; 
   final String description; 
   final int price; 
   final String image; 
   
   Widget build(BuildContext context) {
      return Container(
         padding: EdgeInsets.all(2), 
         height: 140, 
         child: Card( 
            child: Row( 
               mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
               children: <Widget>[ 
                  Image.asset("assets/appimages/" + image), 
                  Expanded( 
                     child: Container( 
                        padding: EdgeInsets.all(5), 
                        child: Column( 
                           mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
                           children: <Widget>[ 
                              Text(this.name, style: 
                                 TextStyle(fontWeight: FontWeight.bold)), 
                              Text(this.description), 
                                 Text("Price: " + this.price.toString()), 
                           ], 
                        )
                     )
                  )
               ]
            )
         )
      ); 
   }
}
  • Erstellen Sie ein neues Widget, MyAnimatedWidget, um einfache Überblendungsanimationen mit Deckkraft zu erstellen.

class MyAnimatedWidget extends StatelessWidget { 
   MyAnimatedWidget({this.child, this.animation}); 
      
   final Widget child; 
   final Animation<double> animation; 
   
   Widget build(BuildContext context) => Center( 
   child: AnimatedBuilder(
      animation: animation, 
      builder: (context, child) => Container( 
         child: Opacity(opacity: animation.value, child: child), 
      ), 
      child: child), 
   ); 
}
  • Hier haben wir AniatedBuilder verwendet, um unsere Animation zu erstellen. AnimatedBuilder ist ein Widget, das seinen Inhalt erstellt und gleichzeitig die Animation ausführt. Es akzeptiert ein Animationsobjekt, um den aktuellen Animationswert abzurufen. Wir haben den Animationswert animation.value verwendet, um die Deckkraft des untergeordneten Widgets festzulegen. Tatsächlich animiert das Widget das untergeordnete Widget mithilfe des Deckkraftkonzepts.

  • Erstellen Sie abschließend das MyHomePage-Widget und animieren Sie den Inhalt mithilfe des Animationsobjekts.

class MyHomePage extends StatelessWidget {
   MyHomePage({Key key, this.title, this.animation}) : super(key: key); 
   
   final String title; 
   final Animation<double> 
   animation; 
   
   @override 
   Widget build(BuildContext context) {
      return Scaffold(
         appBar: AppBar(title: Text("Product Listing")),body: ListView(
            shrinkWrap: true,
            padding: const EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0), 
            children: <Widget>[
               FadeTransition(
                  child: ProductBox(
                     name: "iPhone", 
                     description: "iPhone is the stylist phone ever", 
                     price: 1000, 
                     image: "iphone.png"
                  ), opacity: animation
               ), 
               MyAnimatedWidget(child: ProductBox(
                  name: "Pixel", 
                  description: "Pixel is the most featureful phone ever", 
                  price: 800, 
                  image: "pixel.png"
               ), animation: animation), 
               ProductBox(
                  name: "Laptop", 
                  description: "Laptop is most productive development tool", 
                  price: 2000, 
                  image: "laptop.png"
               ), 
               ProductBox(
                  name: "Tablet", 
                  description: "Tablet is the most useful device ever for meeting", 
                  price: 1500, 
                  image: "tablet.png"
               ), 
               ProductBox(
                  name: "Pendrive", 
                  description: "Pendrive is useful storage medium", 
                  price: 100, 
                  image: "pendrive.png"
               ),
               ProductBox(
                  name: "Floppy Drive", 
                  description: "Floppy drive is useful rescue storage medium", 
                  price: 20, 
                  image: "floppy.png"
               ),
            ],
         )
      );
   }
}

Hier haben wir FadeAnimation und MyAnimationWidget verwendet, um die ersten beiden Elemente in der Liste zu animieren. FadeAnimation ist eine integrierte Animationsklasse, mit der wir das untergeordnete Element mithilfe des Opazitätskonzepts animiert haben.

  • Der vollständige Code lautet wie folgt:

import 'package:flutter/material.dart'; 
void main() => runApp(MyApp()); 

class MyApp extends StatefulWidget { 
   _MyAppState createState() => _MyAppState(); 
} 
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
   Animation<double> animation; 
   AnimationController controller; 
   
   @override 
   void initState() {
      super.initState(); 
      controller = AnimationController(
         duration: const Duration(seconds: 10), vsync: this); 
      animation = Tween<double>(begin: 0.0, end: 1.0).animate(controller); 
      controller.forward(); 
   } 
   // This widget is the root of your application. 
   @override 
   Widget build(BuildContext context) {
      controller.forward(); 
      return MaterialApp( 
         title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue,), 
         home: MyHomePage(title: 'Product layout demo home page', animation: animation,) 
      ); 
   } 
   @override 
   void dispose() {
      controller.dispose();
      super.dispose(); 
   } 
}
class MyHomePage extends StatelessWidget { 
   MyHomePage({Key key, this.title, this.animation}): super(key: key);
   final String title; 
   final Animation<double> animation; 
   
   @override 
   Widget build(BuildContext context) {
      return Scaffold(
         appBar: AppBar(title: Text("Product Listing")), 
         body: ListView(
            shrinkWrap: true, 
            padding: const EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0), 
            children: <Widget>[
               FadeTransition(
                  child: ProductBox(
                     name: "iPhone", 
                     description: "iPhone is the stylist phone ever", 
                     price: 1000, 
                     image: "iphone.png"
                  ), 
                  opacity: animation
               ), 
               MyAnimatedWidget(
                  child: ProductBox( 
                     name: "Pixel", 
                     description: "Pixel is the most featureful phone ever", 
                     price: 800, 
                     image: "pixel.png"
                  ), 
                  animation: animation
               ), 
               ProductBox( 
                  name: "Laptop", 
                  description: "Laptop is most productive development tool", 
                  price: 2000, 
                  image: "laptop.png"
               ), 
               ProductBox(
                  name: "Tablet",
                  description: "Tablet is the most useful device ever for meeting",
                  price: 1500, 
                  image: "tablet.png"
               ), 
               ProductBox(
                  name: "Pendrive", 
                  description: "Pendrive is useful storage medium", 
                  price: 100, 
                  image: "pendrive.png"
               ), 
               ProductBox(
                  name: "Floppy Drive", 
                  description: "Floppy drive is useful rescue storage medium", 
                  price: 20, 
                  image: "floppy.png"
               ), 
            ], 
         )
      ); 
   } 
} 
class ProductBox extends StatelessWidget { 
   ProductBox({Key key, this.name, this.description, this.price, this.image}) :
      super(key: key);
   final String name; 
   final String description; 
   final int price; 
   final String image; 
   Widget build(BuildContext context) {
      return Container(
         padding: EdgeInsets.all(2), 
         height: 140, 
         child: Card(
            child: Row(
               mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
               children: <Widget>[ 
                  Image.asset("assets/appimages/" + image), 
                  Expanded(
                     child: Container( 
                        padding: EdgeInsets.all(5), 
                        child: Column( 
                           mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
                           children: <Widget>[ 
                              Text(
                                 this.name, style: TextStyle(
                                    fontWeight: FontWeight.bold
                                 )
                              ), 
                              Text(this.description), Text(
                                 "Price: " + this.price.toString()
                              ), 
                           ], 
                        )
                     )
                  ) 
               ]
            )
         )
      ); 
   } 
}
class MyAnimatedWidget extends StatelessWidget { 
   MyAnimatedWidget({this.child, this.animation}); 
   final Widget child; 
   final Animation<double> animation; 
 
   Widget build(BuildContext context) => Center( 
      child: AnimatedBuilder(
         animation: animation, 
         builder: (context, child) => Container( 
            child: Opacity(opacity: animation.value, child: child), 
         ), 
         child: child
      ), 
   ); 
}
  • Kompilieren Sie die Anwendung und führen Sie sie aus, um die Ergebnisse anzuzeigen. Die ursprüngliche und endgültige Version der Anwendung lautet wie folgt: