Comme vous l’avez peut-être déjà remarqué, l’une des notions essentielles de Flutter est celle des Widgets.
Ils nous permettent d’ajouter du contenu, mais aussi de bâtir l’architecture de notre application.
Ils sont partout dans notre code Flutter et il me semblait indispensable de vous présenter le plus tôt possible toutes les notions à connaître sur les widgets.
Nous verrons avec l’application de démarrage de Flutter les différents types de widgets ainsi que la bonne syntaxe pour les utiliser.
Pour comprendre les fondamentaux des widgets Flutter, j'ai repris le code de l'application de démarrage Flutter (une simple page avec un titre et du texte).
Ce deuxième exemple d'application Flutter possède un design plus intéressant que notre application vierge précédente.
Cela vous permettra de comprendre l'intérêt et le fonctionnement des Widgets dans Flutter.
Vous pouvez donc copier le code Dart suivant:
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Welcome to Flutter', home: Scaffold( appBar: AppBar( title: const Text('Welcome to Flutter'), ), body: const Center( child: Text('Hello World'), ), ), ); } }
Et enregistrez votre fichier pour visualiser l'application suivante:
Nous allons reprendre chaque ligne de code pour vous faire comprendre l'intérêt de chaque élément.
En ce qui concerne le package nécessaire au fonctionnement de notre application, cela ne change pas:
import 'package:flutter/material.dart';
Il s'agit du package Material de Flutter qui nous permettra d'accéder à de nombreux widgets indispensables à nos applications.
On continue avec la deuxième ligne de code concernant la fonction main():
void main() => runApp(const MyApp());
On remarque le premier changement par rapport à notre code précédent, on retrouve la fonction runApp() mais avec une classe en paramètre.
En fait la fonction runApp() va charger un Widget que nous allons déclarer.
Nous déclarons cette nouvelle classe MyApp sous forme de Widget Flutter de type StatelessWidget:
class MyApp extends StatelessWidget {}
En fait il existe deux types de widgets à connaître pour les bases de Flutter:
Un StatelessWidget nous permet de créer un premier Widget qui peut en contenir plusieurs à son tour et créer tout le contenu de notre page.
Par exemple une page de connexion avec Flutter peut être constitué de StatelessWidget.
Puisque l'affichage et le contenu de la page sera toujours le même, on peut utiliser les StatelessWidgets pour la créer.
Ce type de Widget n'est pas censé se modifier au fil du temps, contrairement aux StatefulWidgets qui eux sont dits mutables.
On utilisera les StatefulWidgets pour toutes les fonctionnalités qui ont besoin de rafraîchir des données ou du contenu.
Par exemple avec l'application Maps que nous allons développer plus loin dans la formation:
Ici lorsqu'on clique sur un marqueur, on affiche une fenêtre avec du contenu, ce qui représente un StatefulWidget typique.
Je vous laisse le lien de la documentation Flutter pour approfondir cette notion: https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html
Nous allons maintenant aborder la syntaxe pour déclarer correctement un StatelessWidget qui va contenir toute notre page.
Vous vous souvenez surement des notions abordées autour des classes en Dart ?
En reprenant la première ligne nous allons pouvoir leur trouver une utilité, notamment de la notion d'héritage:
class MyApp extends StatelessWidget
Vous reconnaissez ici la syntaxe pour déclarer une classe enfant d'une classe parent.
Ici notre classe MyApp hérite de toutes les propriétés de notre classe StatelessWidget créée par Flutter.
Nous utilisons ensuite justement la méthode build issue de la classe StatelessWidget pour retourner le contenu de notre page:
const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Container(color: Colors.blue); }
On utilise l'annotation @override juste avant d'utiliser la méthode build() pour la marquer comme prioritaire par rapport à la classe parent.
Cette notation n'est pas obligatoire, mais fortement recommandée par Flutter qui propose via Visual Studio Code, de l'ajouter à chaque fois que c'est nécessaire.
Du coup on peut reprendre notre méthode build qui retourne le Widget Container avec simplement un fond bleu.
Ainsi voilà le code de votre premier StatelessWidget avec la syntaxe la plus simple:
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Container(color: Colors.blue); } }
Passons maintenant à l'utilisation de Widget plus détaillé concernant l'interface utilisateur.
Nous allons maintenant utiliser les classes MaterialApp() et Scaffold() qui nous fourniront l'interface de base pour nos applications Flutter.
Je vous laisse le lien de la documentation de ces classes pour accéder aux méthodes et propriétés détaillées:
Vous pouvez par exemple retourner le Widget MaterialApp couplé à la classe Scaffold pour créer une application avec une page d'accueil:
return MaterialApp( title: 'Welcome to Flutter', home: Scaffold( appBar: AppBar( title: const Text('Titre de ma page'), ), ), debugShowCheckedModeBanner: false, );
Vous pouvez utiliser le champ debugShowCheckedModeBanner avec la valeur false pour masquer la bannière "debug".
Voilà le résultat de votre application à ce moment-là:
On continue en modifiant juste notre widget Scaffold en lui ajoutant le champ body (pour corps):
home: Scaffold( appBar: AppBar( title: const Text('Welcome to Flutter'), ), body: const Center( child: Text('Hello World'), ), ),
On lui place alors le duo de widget Center() et Text() pour placer du texte centré dans notre page.
Voilà pour le code de notre application Flutter avec cette fois-ci une interface utilisateur plus complète.