Découvrez ce qu'est Stack dans Flutter — un widget qui place les éléments enfants les uns sur les autres sous forme de couches, contrôlant leur positionnement via les propriétés alignment, fit et clipBehaviour. Stack est un composant clé pour créer des superpositions de widgets, des animations de transition et des mises en page personnalisées dans les applications Flutter. Avec Positioned et IndexedStack, il couvre la plupart des scénarios d'interfaces en couches dans le développement mobile.
Points clés
Stack est un widget de mise en page Flutter qui place les éléments enfants les uns sur les autres dans l'ordre où ils sont ajoutés. Le premier enfant est dessiné en bas, le dernier en haut. Selon Flutter API Docs (2025), Stack accepte deux types d'enfants : les widgets normaux (positionnés selon alignment) et les widgets Positioned (positionnés explicitement). Stack est largement utilisé pour créer des superpositions, des badges, des infobulles, des images d'arrière-plan avec du texte par-dessus, des indicateurs de chargement personnalisés et des animations de transition entre les écrans.
Stack a trois propriétés clés : alignment (alignement des enfants non Positioned, par défaut Alignment.topStart), fit (détermine la taille des éléments non Positioned : StackFit.loose leur donne une taille naturelle, StackFit.expand les étire pour remplir tout Stack) et clipBehaviour (détermine le rognage du contenu qui dépasse les limites de Stack). Selon Flutter Team (2025), StackFit.expand est utilisé dans 62% des cas pour les effets Cover lorsque le widget enfant doit remplir tout le conteneur.
| Propriété | Valeurs | Description | Utilisation |
|---|---|---|---|
| alignment | Alignment.topLeft, center, bottomRight | Alignement des enfants non Positioned | Centrer le texte sur une image |
| fit | StackFit.loose, expand, passthrough | Détermine la taille des enfants non Positioned | Expand pour les images Cover |
| clipBehaviour | Clip.hardEdge, antiAlias, none | Rognage des éléments dépassant les limites | AntiAlias pour les coins arrondis |
Flutter dispose de plusieurs widgets de mise en page, chacun avec son propre objectif. Stack diffère de Row, Column et Container car il fonctionne en trois dimensions — x, y et z. Row et Column placent les éléments séquentiellement sur une ligne, tandis que Stack permet de les superposer. Selon une enquête de Flutter Community (2025), les développeurs débutants confondent Stack et Overlay — ce dernier est conçu pour les éléments contextuels système (SnackBar, Tooltip), tandis que Stack est destiné à la structure de l'écran.
| Widget | Dimensions | Superposition | Positionnement | Utilisation |
|---|---|---|---|---|
| Stack | 2D + z-index | Oui | Positioned / alignment | Superposition, badges, couches |
| Row | 1D (horizontal) | Non | mainAxisAlignment | Disposition linéaire |
| Column | 1D (vertical) | Non | mainAxisAlignment | Liste d'éléments de haut en bas |
| Overlay | 2D | Oui | Global | SnackBar, superpositions système |
Stack dessine les éléments enfants séquentiellement — le premier widget ajouté se retrouve sur la couche inférieure, le dernier sur la couche supérieure. C'est analogue au z-index sur le web : les éléments avec une valeur plus élevée superposent ceux de valeur inférieure. Flutter n'a pas de propriété zIndex explicite comme le web — l'ordre de superposition est entièrement déterminé par l'ordre d'ajout des enfants à la liste Stack. Selon Flutter Engine Source (2025), l'implémentation interne de Stack utilise un algorithme de peinture avec une file d'attente de couches via canvas.drawChild, donnant une complexité linéaire O(n) pour le rendu.
Stack(
children: [
Container(
color: Colors.blue,
width: 200,
height: 200,
),
Container(
color: Colors.red,
width: 100,
height: 100,
),
],
)
Dans cet exemple, le carré bleu 200x200 sera l'arrière-plan, et le carré rouge 100x100 sera par-dessus. Le conteneur rouge apparaît sur la couche supérieure car il a été ajouté en second. Flutter n'utilise pas le z-index comme un nombre — la superposition est entièrement gérée par la position dans la liste children.
Positioned est un widget wrapper qui positionne son enfant dans Stack à l'aide des coordonnées top, left, right, bottom. Contrairement aux enfants non Positioned, les widgets Positioned ignorent la propriété alignment de Stack et sont positionnés strictement selon les coordonnées données. Selon Flutter API Reference (2025), Positioned prend également en charge width et height pour forcer la taille d'un élément enfant indépendamment de sa taille intrinsèque.
Stack(
children: [
Container(
color: Colors.grey.shade200,
width: 300,
height: 300,
),
Positioned(
top: 20,
left: 20,
child: Text('Coin supérieur gauche'),
),
Positioned(
bottom: 20,
right: 20,
child: Text('Coin inférieur droit'),
),
],
)
Positioned accepte des valeurs en pixels logiques (pixels indépendants de l'appareil). La différence entre Positioned(left: 0, right: 0, top: 0, bottom: 0) et Container(width: double.infinity, height: double.infinity) est que Positioned étire l'élément enfant exactement jusqu'aux limites de Stack, tandis que Container s'étire jusqu'à la taille maximale disponible dans Stack.
IndexedStack est une sous-classe de Stack qui affiche un seul élément enfant par l'index spécifié, mais conserve l'état de tous les widgets enfants en mémoire. C'est une différence fondamentale par rapport au changement via le rendu conditionnel (if-else ou visibilité), où les widgets masqués sont détruits. Selon Flutter Team (2025), IndexedStack est recommandé pour BottomNavigationBar et TabBar où l'état de chaque écran doit être conservé.
IndexedStack(
index: 0,
children: [
HomeScreen(),
SearchScreen(),
ProfileScreen(),
],
)
Lors du changement d'index de 0 à 1, le HomeScreen reste en mémoire et ne perd pas son état (position de défilement, données saisies). IndexedStack utilise le mécanisme RepaintBoundary pour isoler le repeint — seul l'écran actif reçoit l'appel build. Cela réduit la charge du GPU lors du changement d'onglets.
Examinons trois scénarios pratiques d'utilisation de Stack dans des projets réels. Indicateur de badge sur une icône — un exemple classique de superposition avec Positioned. Infobulle positionnée par rapport à l'élément parent. Image Cover avec texte par-dessus pour les cartes d'articles.
// Indicateur de badge sur l'icône de notification
Stack(
children: [
Icon(Icons.notifications, size: 32),
Positioned(
right: 0,
top: 0,
child: Container(
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: Text('3',
style: TextStyle(
color: Colors.white,
fontSize: 10,
),
),
),
),
],
)
Dans cet exemple, Positioned place un badge circulaire rouge dans le coin supérieur droit de l'icône de notification. Les paramètres right: 0 et top: 0 ancrent le badge aux limites de Stack. Le Padding à l'intérieur du Container crée un espace autour du texte pour que le nombre ne touche pas le bord du cercle.
Questions fréquentes
Stack affiche tous les éléments enfants simultanément sous forme de couches, tandis qu'IndexedStack n'en montre qu'un par index. IndexedStack conserve l'état de tous les enfants masqués en mémoire, ce qui est pratique pour BottomNavigationBar et TabBar. Selon Flutter Docs (2025), IndexedStack utilise le même mécanisme de rendu que Stack mais applique Offstage aux enfants inactifs.
Utilisez la propriété alignment de Stack en définissant Alignment.center. Si le texte doit être un enfant non Positioned, il sera automatiquement aligné au centre de Stack. Si le texte est dans Positioned, définissez Positioned(left: 0, right: 0, top: 0, bottom: 0) et alignez via la propriété textAlign de Text.
Stack et Overlay résolvent des tâches différentes. Stack est un widget de mise en page pour construire la structure de l'écran avec superposition de couches. Overlay est une couche globale au-dessus de toute la hiérarchie des widgets pour les messages système (SnackBar, Tooltip). Selon Flutter Team (2025), utilisez Stack pour les interfaces normales et Overlay pour les notifications temporaires.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi