Animer des applications avec Flutter
A propos de l’auteur
Un développeur de logiciels full stack le jour et un développeur d’applications mobiles la nuit. Quand je ne travaille pas, j’aime cuisiner et jouer à des jeux sur PC.En savoir plus surShubham↬
- 14 min de lecture
- Applications,Animation
- Enregistré pour une lecture hors ligne
- Partager sur Twitter, LinkedIn
Les apps pour n’importe quelle plateforme sont louées lorsqu’elles sont intuitives, belles et fournissent un retour agréable aux interactions de l’utilisateur. L’animation est l’un des moyens d’y parvenir.
Flutter, un framework multiplateforme, a mûri au cours des deux dernières années pour inclure un support web et de bureau. Il a acquis la réputation que les applications développées avec lui sont fluides et belles. Avec sa riche prise en charge des animations, sa façon déclarative d’écrire l’interface utilisateur, le « Hot Reload » et d’autres fonctionnalités, il est maintenant un framework multiplateforme complet.
Si vous débutez avec Flutter et que vous voulez apprendre une façon non conventionnelle d’ajouter des animations, alors vous êtes au bon endroit : nous allons explorer le royaume des widgets d’animation et de mouvement, une façon implicite d’ajouter des animations.
Flutter est basé sur le concept des widgets. Chaque composant visuel d’une application est un widget – pensez à eux comme à des vues dans Android. Flutter fournit un support d’animation en utilisant une classe Animation, un objet « AnimationController » pour la gestion, et « Tween » pour interpoler la plage de données. Ces trois composants fonctionnent ensemble pour fournir une animation fluide. Comme cela nécessite une création et une gestion manuelles de l’animation, c’est connu comme une façon explicite d’animer.
Maintenant, laissez-moi vous présenter les widgets d’animation et de mouvement. Flutter fournit de nombreux widgets qui supportent intrinsèquement l’animation. Il n’est pas nécessaire de créer un objet d’animation ou un quelconque contrôleur, car toute l’animation est gérée par cette catégorie de widgets. Il suffit de choisir le widget approprié pour l’animation requise et de transmettre les valeurs des propriétés du widget à animer. Cette technique est une manière implicite d’animer.
Le tableau ci-dessus établit grossièrement la hiérarchie des animations dans Flutter, comment les animations explicites et implicites sont prises en charge.
Certains des widgets animés couverts dans cet article sont :
AnimatedOpacity
AnimatedCrossFade
AnimatedAlign
AnimatedPadding
AnimatedSize
-
AnimatedPositioned
.
Flutter fournit non seulement des widgets animés prédéfinis mais aussi un widget générique appelé AnimatedWidget
, qui peut être utilisé pour créer des widgets personnalisés implicitement animés. Comme il ressort de leur nom, ces widgets appartiennent à la catégorie des widgets animés et de mouvement, et ils ont donc des propriétés communes qui nous permettent de rendre les animations beaucoup plus fluides et plus belles.
Laissons-moi expliquer ces propriétés communes maintenant, car elles seront utilisées plus tard dans tous les exemples.
-
duration
La durée sur laquelle animer les paramètres. -
reverseDuration
La durée de l’animation inverse. -
curve
La courbe à appliquer lors de l’animation des paramètres. Les valeurs interpolées peuvent être tirées d’une distribution linéaire ou, si et quand cela est spécifié, peuvent être tirées d’une courbe.
Débutons le voyage en créant une application simple que nous appellerons « Quoted ». Elle affichera une citation aléatoire à chaque fois que l’app démarrera. Deux choses à noter : premièrement, toutes ces citations seront codées en dur dans l’application ; et deuxièmement, aucune donnée utilisateur ne sera sauvegardée.
Note : Tous les fichiers de ces exemples peuvent être trouvés sur GitHub.
Démarrer
Flutter devrait être installé et vous devrez vous familiariser avec le flux de base avant de continuer. Un bon endroit pour commencer est, « Using Google’s Flutter For Truly Cross-Platform Mobile Development ».
Créer un nouveau projet Flutter dans Android Studio.
Cela ouvrira un nouvel assistant de projet, où vous pourrez configurer les bases du projet.
Dans l’écran de sélection du type de projet, il existe différents types de projets Flutter, chacun répondant à un scénario spécifique…. Pour ce tutoriel, choisissez Flutter Application et appuyez sur Suivant.
Vous devez maintenant entrer certaines informations spécifiques au projet : le nom et le chemin du projet, le domaine de l’entreprise, et ainsi de suite. Jetez un œil à l’image ci-dessous.
Ajouter le nom du projet, le chemin du SDK Flutter, l’emplacement du projet et une description facultative du projet. Appuyez sur Suivant.
Chaque application (qu’elle soit Android ou iOS) nécessite un nom de paquet unique. Typiquement, vous utilisez l’inverse du domaine de votre site web ; par exemple, com.google ou com.yahoo. Appuyez sur Terminer pour générer une application Flutter fonctionnelle.
Une fois le projet généré, vous devriez voir l’écran présenté ci-dessus. Ouvrez le fichier main.dart (mis en évidence dans la capture d’écran). Il s’agit du fichier principal de l’application. Le projet d’exemple est complet en lui-même, et peut être exécuté directement sur un émulateur ou un appareil physique sans aucune modification.
Remplacez le contenu du fichier main.dart par le bout de code suivant :
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(), ); }}
Ce code nettoie le fichier main.dart en ajoutant simplement des informations simples pertinentes pour créer une nouvelle application. La classe MyApp renvoie un objet : un widget MaterialApp
, qui fournit la structure de base pour créer des apps conformes au Material Design. Pour rendre le code plus structuré, créez deux nouveaux fichiers dart dans le dossier lib : FirstPage.dart et Quotes.dart.
FirstPage.dart contiendra tout le code responsable de tous les éléments visuels (widgets) nécessaires à notre application Citations. Toute l’animation est gérée dans ce fichier.
Note : Plus loin dans l’article, tous les extraits de code pour chaque widget animé sont ajoutés à ce fichier comme enfants du widget Scaffold. Pour plus d’informations, Cet exemple sur GitHub pourrait être utile.
Débutez en ajoutant le code suivant à FirstPage.dart. C’est le code partiel où d’autres choses seront ajoutées plus tard.
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; } @override Widget build(BuildContext context) { screenWidth = MediaQuery.of(context).size.width; screenHeight = MediaQuery.of(context).size.height; return Scaffold( appBar: _getAppBar(), body: Stack( children: , ), ); }}
Le fichier Quotes.dart contient une liste de toutes les citations codées en dur. Un point à noter ici est que la liste est un objet statique. Cela signifie qu’elle peut être utilisée à d’autres endroits sans créer un nouvel objet de la classe Quotes. Ceci est choisi par conception, car la liste ci-dessus agit simplement comme un utilitaire.
Ajoutez le code suivant à ce fichier:
class Quotes { static const quotesArray = ;}
Le squelette du projet est maintenant prêt, alors étoffons Citation un peu plus.
AnimatedOpacity
Pour donner une touche personnelle à l’application, il serait bien de connaître le nom de l’utilisateur, alors demandons-le et montrons un bouton suivant. Jusqu’à ce que l’utilisateur entre son nom, ce bouton est caché, et il s’affichera gracieusement lorsqu’un nom sera donné. Nous avons besoin d’une sorte d’animation de visibilité pour le bouton, mais existe-t-il un widget pour cela ? Oui, il y en a un.
Enter AnimatedOpacity
. Ce widget s’appuie sur le widget Opacity en ajoutant un support d’animation implicite. Comment l’utiliser ? Rappelez-vous notre scénario : nous avons besoin d’afficher un bouton suivant avec une visibilité animée. Nous enveloppons le widget bouton à l’intérieur du widget AnimatedOpacity
, alimentons quelques valeurs appropriées et ajoutons une condition pour déclencher l’animation – et Flutter peut gérer le reste.
_getAnimatedOpacityButton() { return AnimatedOpacity( duration: Duration(seconds: 1), reverseDuration: Duration(seconds: 1), curve: Curves.easeInOut, opacity: showNextButton ? 1 : 0, child: _getButton(), );}
Le widget AnimatedOpacity
a deux propriétés obligatoires:
-
opacity
Une valeur de 1 signifie complètement visible ; 0 (zéro) signifie caché. Pendant l’animation, Flutter interpole les valeurs entre ces deux extrêmes. Vous pouvez voir comment une condition est placée pour changer la visibilité, déclenchant ainsi l’animation. -
child
Le widget enfant qui aura sa visibilité animée.
Vous devriez maintenant comprendre comment il est vraiment simple d’ajouter une animation de visibilité avec le widget implicite. Et tous ces widgets suivent les mêmes directives et sont faciles à utiliser. Passons au suivant.
AnimatedCrossFade
Nous avons le nom de l’utilisateur, mais le widget attend toujours une entrée. Dans l’étape précédente, lorsque l’utilisateur saisit son nom, nous affichons le bouton suivant. Maintenant, lorsque l’utilisateur appuie sur le bouton, je veux arrêter d’accepter la saisie et afficher le nom saisi. Il y a de nombreuses façons de le faire, bien sûr, mais nous pouvons peut-être cacher le widget de saisie et afficher un widget de texte non modifiable. Essayons-le en utilisant le widget AnimatedCrossFade
.
Ce widget nécessite deux enfants, car le widget passe de l’un à l’autre en fonction d’une certaine condition. Une chose importante à garder à l’esprit lors de l’utilisation de ce widget est que les deux enfants doivent avoir la même largeur. Si la hauteur est différente, le widget le plus grand sera coupé en bas. Dans ce scénario, deux widgets seront utilisés comme enfants : input et 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, );}
Ce widget nécessite un ensemble différent de paramètres obligatoires:
-
crossFadeState
Cet état travaille sur quel enfant montrer. -
firstChild
Spécifie le premier enfant pour ce widget. -
secondChild
Spécifie le deuxième enfant.
AnimatedAlign
À ce stade, l’étiquette du nom est positionnée au centre de l’écran. Elle aura bien meilleure allure en haut, car nous avons besoin du centre de l’écran pour afficher les guillemets. En d’autres termes, l’alignement du widget de l’étiquette du nom doit passer du centre au sommet. Et ne serait-il pas agréable d’animer ce changement d’alignement en même temps que l’animation de fondu enchaîné précédente ? Faisons-le.
Comme toujours, plusieurs techniques peuvent être utilisées pour y parvenir. Puisque le widget d’étiquette de nom est déjà aligné au centre, l’animation de son alignement serait beaucoup plus simple que de manipuler les valeurs haut et gauche du widget. Le widget AnimatedAlign
est parfait pour ce travail.
Pour lancer cette animation, un déclencheur est nécessaire. Le seul but de ce widget est d’animer le changement d’alignement, il n’a donc que quelques propriétés : ajouter un enfant, définir son alignement, déclencher le changement d’alignement, et c’est tout.
_getAnimatedAlignWidget() { return AnimatedAlign(duration: Duration(seconds: 1),curve: Curves.easeInOut,alignment: alignTop ? Alignment.topLeft : Alignment.center,child: _getAnimatedCrossfade(), );}
Il n’a que deux propriétés obligatoires :
- child:
L’enfant dont l’alignement sera modifié. - alignment:
Valeur d’alignement requise.
Ce widget est vraiment simple mais les résultats sont élégants. De plus, nous avons vu avec quelle facilité nous pouvons utiliser deux widgets animés différents pour créer une animation plus complexe. C’est la beauté des widgets animés.
AnimatedPadding
Maintenant, nous avons le nom de l’utilisateur en haut, animé en douceur sans beaucoup d’efforts, en utilisant différents types de widgets animés. Ajoutons une salutation, « Hi », avant le nom. L’ajout d’un widget de texte avec la valeur « Hi, » en haut fera en sorte qu’il chevauche le widget de texte de salutation, ressemblant à l’image ci-dessous.
Et si le widget de texte de nom avait un certain padding à gauche ? Augmenter le padding à gauche fonctionnera certainement, mais attendez : pouvons-nous augmenter le padding avec une certaine animation ? Oui, et c’est ce que fait AnimatedPadding
. Pour rendre tout cela beaucoup plus beau, faisons en sorte que le widget de texte de salutations s’estompe et que le rembourrage du widget de texte de nom augmente en même temps.
_getAnimatedPaddingWidget() { return AnimatedPadding( duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn, padding: increaseLeftPadding ? EdgeInsets.only(left: 28.0) : EdgeInsets.only(left: 0), child: _getAnimatedCrossfade(), );}
Puisque l’animation ci-dessus devrait se produire seulement après que l’alignement animé précédent soit terminé, nous devons retarder le déclenchement de cette animation. En s’éloignant brièvement du sujet, c’est le bon moment pour parler d’un mécanisme populaire pour ajouter un délai. Flutter propose plusieurs techniques de ce type, mais le constructeur Future.delayed est l’une des approches les plus simples, les plus propres et les plus lisibles. Par exemple, pour exécuter un morceau de code après 1 seconde:
Future.delayed(Duration(seconds: 1), (){ sum = a + b; // This sum will be calculated after 1 second. print(sum);});
Puisque la durée du délai est déjà connue (calculée à partir des durées d’animation précédentes), l’animation peut être déclenchée après cet intervalle.
// 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; }); });}
Ce widget n’a que deux propriétés obligatoires:
-
child
L’enfant à l’intérieur de ce widget, auquel le padding sera appliqué. -
padding
La quantité d’espace à ajouter.
AnimatedSize
Aujourd’hui, toute application ayant une certaine forme d’animation inclura un zoom avant ou arrière sur les composants visuels pour attirer l’attention de l’utilisateur (communément appelé animation de mise à l’échelle). Pourquoi ne pas utiliser la même technique ici ? Nous pouvons montrer à l’utilisateur une citation motivante qui zoome depuis le centre de l’écran. Laissez-moi vous présenter le widget AnimatedSize
, qui active les effets de zoom avant et de zoom arrière, contrôlés par la modification de la taille de son enfant.
Ce widget est un peu différent des autres en ce qui concerne les paramètres requis. Nous avons besoin de ce que Flutter appelle un « Ticker ». Flutter a une méthode pour faire savoir aux objets chaque fois qu’un nouvel événement de trame est déclenché. On peut l’imaginer comme quelque chose qui envoie un signal disant « Fais-le maintenant ! … Faites-le maintenant ! … Faites-le maintenant ! … »
Le widget AnimatedSize
nécessite une propriété – vsync – qui accepte un fournisseur de ticker. La façon la plus simple d’obtenir un fournisseur de téléscripteur est d’ajouter un Mixin à la classe. Il existe deux implémentations de base de fournisseur de téléscripteur : SingleTickerProviderStateMixin
, qui fournit un seul ticker ; et TickerProviderStateMixin
, qui en fournit plusieurs.
L’implémentation par défaut d’un ticker est utilisée pour marquer les images d’une animation. Dans ce cas, c’est cette dernière qui est employée. En savoir plus sur les 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; }); });}
Propriétés obligatoires pour ce widget :
-
vsync
Le fournisseur de téléscripteur requis pour coordonner l’animation et les changements de trame.< -
child
L’enfant dont les changements de taille seront animés.
L’animation de zoom avant et de zoom arrière est maintenant facilement apprivoisée.
AnimatedPositioned
Génial ! Les citations zooment depuis le centre pour attirer l’attention de l’utilisateur. Et si elles glissaient vers le haut depuis le bas tout en zoomant ? Essayons. Cette motion implique de jouer avec la position du widget de citation et d’animer les changements de propriétés de position. AnimatedPositioned
est le candidat parfait.
Ce widget fait automatiquement transiter la position de l’enfant sur une durée donnée dès que la position spécifiée change. Un point à noter : il ne fonctionne que si son widget parent est un « Stack ». Ce widget est assez simple et direct à utiliser. Voyons voir.
// 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, );}
Ce widget n’a qu’une seule propriété obligatoire:
-
child
Le widget dont la position sera modifiée.
Si la taille de l’enfant n’est pas censée changer en même temps que sa position, une alternative plus performante à ce widget serait SlideTransition
.
Voici notre animation complète:
Conclusion
Les animations font partie intégrante de l’expérience utilisateur. Les apps statiques ou les apps avec des animations bancales diminuent non seulement la rétention des utilisateurs mais aussi la réputation d’un développeur à fournir des résultats.
Aujourd’hui, la plupart des apps populaires ont une sorte d’animation subtile pour ravir les utilisateurs. Les réactions animées aux demandes des utilisateurs peuvent également les inciter à explorer davantage. Flutter offre beaucoup de fonctionnalités pour le développement multiplateforme, y compris un support riche pour des animations fluides et réactives.
Flutter a un grand support de plug-in qui nous permet d’utiliser les animations d’autres développeurs. Maintenant qu’il a mûri jusqu’à la version 1.9, avec tant d’amour de la part de la communauté, Flutter ne peut que s’améliorer à l’avenir. Je dirais que c’est le moment idéal pour apprendre Flutter!
Leave a Reply