Android hat eine sehr interessante Funktion der View-Animation namens CircularRevealAnimation
- wörtlich "Circular Disclosure". Flutter wiederum bietet eine solche Animation nicht sofort, obwohl es umfangreiche Funktionen zum Animieren von Widgets bietet.

Dieser Artikel zeigt, wie solche Animationen mit Flutter implementiert und die Bibliothek auf pub.dev veröffentlicht werden, um den Zugriff und die Verteilung zu vereinfachen.
Implementierung der Animation
In Flutter ist alles ein Widget. Und Animation ist keine Ausnahme. Daher erstellen wir die CircularRevealAnimation
Klasse, die die StatelessWidget
Klasse erweitert.
Das Starten, Stoppen und andere Steuerelemente für Animationen werden mit dem AnimationController
. Um einen AnimationController
zu erstellen AnimationController
Sie von StatefulWidget
erben und State
eine spezielle Klasse SingleTickerProviderStateMixin
hinzufügen.
Unsere Animationsklasse CircularRevealAnimation
ist nicht für die Verwaltung der Animation selbst verantwortlich, sondern erhält Animation<double>
als erforderlichen Konstruktorparameter, sodass keine Notwendigkeit besteht, von StatefulWidget
zu erben. Dies geschieht, damit die CircularRevealAnimation
problemlos mit anderen Animationen kombiniert werden kann, die denselben AnimationController
. Kombinieren Sie beispielsweise eine Offenlegungsanimation mit einer Transparenzänderungsanimation.
Ein weiterer wichtiger Parameter des CircularRevealAnimation
Konstruktors ist das untergeordnete Element, das ein untergeordnetes Widget unserer Animation ist und angezeigt oder ausgeblendet wird. Im Allgemeinen haben in Flutter viele Widgets einen child
Parameter. Mit solchen Widgets können Sie das Verhalten, das Rendern oder das Layout eines untergeordneten Widgets ändern. Oder fügen Sie eine Animation hinzu, wie dies bei CircularRevealAnimation
.
Um eine Animation anzugeben, benötigen Sie außerdem Parameter wie die Mitte des Öffnens (oder Schließens) der Animation sowie die minimalen und maximalen Offenlegungsradien. Diese Parameter sind optional und können beim Erstellen einer Animation als null
oder gar nicht angegeben werden. In diesem Fall werden die Standardwerte verwendet: Das Offenlegungszentrum befindet sich in der Mitte des Widgets, der minimale Radius wird auf Null verwundet und der maximale Radius entspricht dem Abstand vom Offenlegungszentrum zum Scheitelpunkt des Widgets, der am weitesten vom Offenlegungszentrum entfernt ist.
Der Standardalgorithmus zur Berechnung des maximalen Radius lautet wie folgt. Zuerst werden die horizontalen und vertikalen Abstände vom Zentrum zum Scheitelpunkt berechnet, die am weitesten vom Offenbarungszentrum entfernt sind, und dann wird die Diagonale nach dem Satz von Pythagoras berechnet.
static double calcMaxRadius(Size size, Offset center) { final w = max(center.dx, size.width - center.dx); final h = max(center.dy, size.height - center.dy); return sqrt(w * w + h * h); }
Jetzt müssen Sie das Zuschneiden des Widgets innerhalb des Kreises während des Renderns implementieren. Die ClipPath
Klasse hilft uns dabei, ClipPath
Sie das Widget nach einer beliebigen Vorlage zuschneiden können. Als Parameter wird diesem Widget clipper
(etwas später) und child
ist das untergeordnete Widget, das zugeschnitten werden muss.
Der Parameter clipper
des ClipPath
Widgets bestimmt, wie das ClipPath
Widget ClipPath
wird. Um Ihre eigene Zuschneidevorlage zu erstellen, erstellen Sie die CircularRevealClipper
Klasse, die die CustomClipper<Path>
-Klasse erbt, und definieren Sie die Path getClip(Size size)
Methode Path getClip(Size size)
. Diese Methode gibt einen Path
, der den Zuschneidebereich begrenzt. In unserem Fall ist diese Region ein Kreis mit einem bestimmten Mittelpunkt. Um den Radius eines Kreises zu berechnen, müssen Sie den aktuellen Wert der Animation kennen. Dieser Wert wird als Bruchparameter an CircularRevealClipper
. Der Radius des Kreises wird durch lineare Interpolation zwischen dem minimalen und dem maximalen Radius berechnet.
Danach fahren wir mit der Implementierung des Widgets fort. Es ist praktisch, AnimatedBuilder
zum Erstellen einer Animation zu verwenden. Der AnimatedBuilder
Konstruktor akzeptiert das Animation<double>
und den builder
, mit denen Widgets basierend auf dem aktuellen Animationswert erstellt werden. Im builder
erstellen wir einen ClipPath
und übergeben den aktuellen Wert der Animation ( fraction
) an CircularRevealClipper
.
class CircularRevealAnimation extends StatelessWidget { ... @override Widget build(BuildContext context) { return AnimatedBuilder( animation: animation, builder: (BuildContext context, Widget _) { return ClipPath( clipper: CircularRevealClipper( fraction: animation.value, center: center, minRadius: minRadius, maxRadius: maxRadius, ), child: this.child, ); }, ); } }
Damit ist die Erstellung der CircularRevealAnimation
. Es bleibt zu benutzen. Erstellen Sie dazu ein StatefulWidget
, AnimationController
und übergeben Sie den AnimationController
an CircularRevealAnimation
.
Anwendungsbeispiel import 'package:flutter/material.dart'; import 'package:circular_reveal_animation/circular_reveal_animation.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'CRA Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin { AnimationController animationController; Animation<double> animation; @override void initState() { super.initState(); animationController = AnimationController( vsync: this, duration: Duration(milliseconds: 1000), ); animation = CurvedAnimation( parent: animationController, curve: Curves.easeIn, ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("CRA Demo"), ), body: Padding( padding: const EdgeInsets.all(16.0), child: CircularRevealAnimation( minRadius: 12, maxRadius: 200, center: Offset(0, 300), child: Container(color: Colors.red), animation: animation, ), ), floatingActionButton: FloatingActionButton(onPressed: () { if (animationController.status == AnimationStatus.forward || animationController.status == AnimationStatus.completed) { animationController.reverse(); } else { animationController.forward(); } }), ); } }
Github Demo App .
Bibliothekserstellung
Um eine Dart- oder Flutter-Bibliothek zu erstellen, müssen Sie die Datei pubspec.yaml
demselben Verzeichnis wie das lib
Verzeichnis mit den Dart-Dateien hinzufügen. Diese Datei enthält eine Beschreibung der Bibliothek, Informationen zu Autoren und Abhängigkeiten.
Es wird auch empfohlen, eine Datei zu erstellen, die eine öffentliche API definiert. Diese Datei befindet sich im Ordner lib
und enthält den Namen der Bibliothek sowie eine Liste der Dateien, die in die öffentliche API aufgenommen werden müssen. Alle anderen Dart-Dateien werden im src
Verzeichnis abgelegt. Dadurch werden nicht nur Dateien ausgeblendet, die nicht in der öffentlichen API enthalten sind, sondern Sie können die Bibliothek auch mit einem einzigen import
. Der Inhalt dieser Datei :
library circular_reveal_animation; export 'package:circular_reveal_animation/src/circular_reveal_animation.dart';
Weitere Informationen zum Erstellen von Bibliotheken auf Dart finden Sie hier .
Das Veröffentlichen einer Dart-Bibliothek in pub.dev ist sehr einfach. Alles, was Sie tun müssen, ist, den Befehl flutter packages pub publish
im Stammverzeichnis der Bibliothek auszuführen. Die Veröffentlichung erfolgt im Auftrag eines Google-Kontos. Während des Veröffentlichungsprozesses wird daher ein Link angegeben, der in einem Browser geöffnet und bei Google angemeldet werden muss. Anschließend können Aktualisierungen nur über das Konto veröffentlicht werden, in dessen Auftrag die erste Version veröffentlicht wurde.
Es wird empfohlen, vor dem Veröffentlichen zu überprüfen, ob die Bibliothek korrekt ist, indem Sie den flutter packages pub publish --dry-run
.
Nach dem Ausführen von flutter packages pub publish
Bibliothek sofort auf pub.dev verfügbar. Und wie in der Dokumentation angegeben, "Veröffentlichen ist für immer" - später können Sie nur neue Versionen hochladen. Ältere Versionen werden ebenfalls verfügbar sein.
Obwohl das Veröffentlichen von Bibliotheken einfach aussieht, kann es auch Fallstricke geben. Als ich zum Beispiel die erste Version veröffentlichte, wurden mir einige Punkte in der Bewertung abgenommen, weil die Beschreibung der Bibliothek (in pubspec.yaml
) zu kurz war.
Weitere Informationen zum Veröffentlichen von Bibliotheken finden Sie hier .
Eigentlich die Bibliothek circular_reveal_animation
auf pub.dev und github.com .
PS: Ich habe ```java {...} ```
, um den Dart-Code hervorzuheben. Es wäre schön, Dart-Code-Hervorhebungen auf habr.com hinzuzufügen.