Scaffold et AppBar, il est temps d'apprendre à organiser plusieurs widgets ensemble. Dans ce chapitre, nous découvrirons des widgets essentiels pour créer des interfaces plus riches : Container pour styliser, Column et Row pour organiser, et Card pour présenter du contenu. Chaque widget sera introduit progressivement, avec du code minimal et clair.
2.4Organisation de l'interface
2.4.1 – Découvrir Container
Jusqu'à présent, nous avons affiché du texte simple. Pour créer des interfaces plus attrayantes, nous avons besoin de widgets qui permettent de styliser et d'organiser le contenu. Le widget Container est l'un des plus utiles pour cela.
🎨 Pourquoi utiliser un Container ?
Container est un widget polyvalent qui permet de :
- Définir une taille (largeur, hauteur)
- Ajouter des couleurs de fond
- Ajouter des marges et du padding (espacement)
- Centrer ou aligner son contenu
Container dans Flutter ressemble beaucoup à une balise <div> en HTML : c'est une boîte polyvalente dans laquelle on peut placer du contenu, choisir sa taille, sa couleur, ajouter des marges (autour), du padding (à l'intérieur), etc. Cela permet de structurer et styliser visuellement tout ce que l’on veut, comme on le ferait avec un <div> sur une page web.
📏 Taille, couleur et marges simples
Commençons par les propriétés les plus simples de Container :
Container(
width: 200,
height: 100,
color: Colors.blue,
child: Text('Bonjour'),
)
Analysons ce code :
width: 200: Définit la largeur du container (200 pixels)height: 100: Définit la hauteur du container (100 pixels)color: Colors.blue: Définit la couleur de fond (bleu)child: Text('Bonjour'): Le contenu du container (un texte)
Colors est une classe fournie par Flutter qui contient des couleurs prédéfinies. Colors.blue est le bleu standard. Il existe beaucoup d'autres couleurs : Colors.red, Colors.green, Colors.yellow, etc.
Vous pouvez utiliser une couleur prédéfinie simplement comme
Colors.blue.Mais vous pouvez aussi utiliser une nuance précise avec la syntaxe
Colors.nom[index], par exemple :Colors.blue[100]: bleu très clairColors.blue[700]: bleu très foncé- Plus l’index (par exemple 100, 200, ..., 900) est élevé, plus la couleur est foncée.
Exemple :
Container(color: Colors.red[200]) affichera un rouge pâle.
📦 Container + child
Comme beaucoup de widgets Flutter, Container utilise le paramètre child pour définir son contenu. Voici un exemple complet dans une application :
Container en Flutter : largeur, hauteur, couleur et enfant.import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Mon Application'),
),
body: SafeArea(
child: Center(
child: Container(
width: 200,
height: 100,
color: Colors.blue,
child: Center(
child: Text('Bonjour Flutter !'),
),
),
),
),
),
);
}
}
Dans cet exemple :
- Nous avons un
Containerbleu de 200 pixels de large et 100 pixels de haut - À l'intérieur, il y a un
Centerqui centre le texte - Le texte "Bonjour Flutter !" est affiché au centre du container bleu
Pour centrer le texte dans un
Container, nous devons utiliser un widget Center à l'intérieur. Le Container lui-même ne centre pas automatiquement son contenu.
🎨 Ajouter des marges
Les marges créent de l'espace autour du container. Utilisez le paramètre margin :
Container(
width: 200,
height: 100,
color: Colors.blue,
margin: EdgeInsets.all(20),
padding: EdgeInsets.only(left: 10, top: 20),
child: Center(
child: Text('Bonjour'),
),
)
EdgeInsets.all(20) ajoute 20 pixels de marge de tous les côtés (haut, bas, gauche, droite).
EdgeInsets est une classe Flutter pour définir les espacements. EdgeInsets.all(20) ajoute 20 pixels partout. Vous pouvez aussi utiliser EdgeInsets.only(left: 10, top: 20) pour définir des marges ou des paddings spécifiques.
💡 Points clés à retenir
Containerpermet de styliser et organiser le contenuwidthetheightdéfinissent la taillecolordéfinit la couleur de fondmarginajoute de l'espace autour du containerchilddéfinit le contenu du container
Dans la section suivante, nous allons découvrir
Column, un widget qui permet d'organiser plusieurs widgets verticalement (les uns en dessous des autres).
2.4.2 – Organiser en colonne avec Column
Jusqu'à présent, nous avons affiché un seul widget à la fois. Pour créer des interfaces plus riches, nous devons pouvoir afficher plusieurs widgets ensemble. Le widget Column permet d'organiser plusieurs widgets verticalement (les uns en dessous des autres).
📐 Disposition verticale
Column organise ses enfants de haut en bas, en colonne. C'est parfait pour créer des listes verticales d'éléments.
Imaginez une pile de livres. Les livres sont empilés verticalement, un au-dessus de l'autre.
Column fonctionne de la même manière : il empile les widgets verticalement.
📋 children : []
Contrairement aux widgets que nous avons vus jusqu'à présent (qui utilisent child pour un seul enfant), Column utilise children (au pluriel) pour accepter plusieurs widgets. C'est une liste de widgets.
Column empile ses enfants verticalement, comme une pile de blocs.
Voici la structure de base :
Column(
children: [
Text('Premier élément'),
Text('Deuxième élément'),
Text('Troisième élément'),
],
)
Dans cet exemple, children: [...] contient une liste de trois widgets Text(). Ils seront affichés les uns en dessous des autres.
En Dart,
[ ] crée une liste. Les éléments sont séparés par des virgules. Ici, nous créons une liste de widgets. C'est la première fois que nous utilisons une liste, mais c'est très simple : c'est juste une collection d'éléments entre crochets.
🧪 Exemple complet avec Column
Voici un exemple complet dans une application :
Column qui aligne trois widgets Text verticalement.
import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Mon Application'),
),
body: SafeArea(
child: Center(
child: Column(
children: [
Text('Premier élément'),
Text('Deuxième élément'),
Text('Troisième élément'),
],
),
),
),
),
);
}
}
Dans cet exemple, les trois textes seront affichés verticalement, centrés à l'écran.
🎯 Alignement main et cross
Column permet de contrôler l'alignement de ses enfants. Il y a deux axes :
- Axe principal (main axis) : L'axe vertical (haut-bas). C'est l'axe le long duquel les éléments sont empilés.
- Axe secondaire (cross axis) : L'axe horizontal (gauche-droite). C'est l'axe perpendiculaire à l'empilement.
Pour aligner les enfants, utilisez les paramètres mainAxisAlignment et crossAxisAlignment :
Column(
spacing: 10,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Premier'),
Text('Deuxième'),
Text('Troisième'),
],
)
Analysons ces paramètres :
mainAxisAlignment: MainAxisAlignment.center: Centre les éléments verticalement (le long de l'axe principal)crossAxisAlignment: CrossAxisAlignment.center: Centre les éléments horizontalement (le long de l'axe secondaire)spacing: 10: Ajoute un espace de 10 pixels entre les éléments
Column.
MainAxisAlignment.start: Aligne en haut (par défaut)MainAxisAlignment.center: Centre verticalementMainAxisAlignment.end: Aligne en basMainAxisAlignment.spaceBetween: Répartit l'espace entre les élémentsMainAxisAlignment.spaceAround: Répartit l'espace autour des éléments
Pour l'instant, utilisez simplement
mainAxisAlignment: MainAxisAlignment.center et crossAxisAlignment: CrossAxisAlignment.center pour centrer vos éléments. Nous explorerons les autres options plus tard.
💡 Points clés à retenir
Columnorganise les widgets verticalement (de haut en bas)- Il utilise
children: []pour accepter plusieurs widgets (une liste) mainAxisAlignmentcontrôle l'alignement verticalcrossAxisAlignmentcontrôle l'alignement horizontal- Les éléments sont séparés par des virgules dans la liste
Dans la section suivante, nous allons découvrir
Row, qui fonctionne comme Column mais organise les widgets horizontalement (de gauche à droite).
2.4.3 – Organiser en ligne avec Row
Dans la section précédente, nous avons découvert Column qui organise les widgets verticalement. Maintenant, découvrons Row, qui fonctionne de la même manière mais organise les widgets horizontalement (de gauche à droite).
➡️ Disposition horizontale
Row organise ses enfants de gauche à droite, en ligne. C'est parfait pour créer des barres horizontales d'éléments.
Row sont placés horizontalement, de gauche à droite.Imaginez des mots sur une ligne de texte. Les mots sont placés horizontalement, un à côté de l'autre.
Row fonctionne de la même manière : il place les widgets côte à côte horizontalement.
📋 children : []
Comme Column, Row utilise children (au pluriel) pour accepter plusieurs widgets :
Row(
children: [
Text('Premier'),
Text('Deuxième'),
Text('Troisième'),
],
)
Dans cet exemple, les trois textes seront affichés horizontalement, côte à côte.
🧪 Exemple complet avec Row
Voici un exemple complet dans une application :
Row pour placer plusieurs widgets horizontalement.import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Mon Application'),
),
body: SafeArea(
child: Center(
child: Row(
children: [
Text('Premier'),
Text('Deuxième'),
Text('Troisième'),
],
),
),
),
),
);
}
}
Dans cet exemple, les trois textes seront affichés horizontalement, centrés à l'écran.
🎯 Alignements de base
Comme Column, Row permet de contrôler l'alignement. Mais attention : pour Row, les axes sont inversés !
- Axe principal (main axis) : L'axe horizontal (gauche-droite). C'est l'axe le long duquel les éléments sont alignés.
- Axe secondaire (cross axis) : L'axe vertical (haut-bas). C'est l'axe perpendiculaire à l'alignement.
Row(
spacing: 10,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Premier'),
Text('Deuxième'),
Text('Troisième'),
],
)
Pour Row :
mainAxisAlignment: MainAxisAlignment.center: Centre les éléments horizontalement (le long de l'axe principal)crossAxisAlignment: CrossAxisAlignment.center: Centre les éléments verticalement (le long de l'axe secondaire)spacing: 10: Ajoute un espace de 10 pixels entre les éléments
- Column : Axe principal = vertical (haut-bas), Axe secondaire = horizontal (gauche-droite)
- Row : Axe principal = horizontal (gauche-droite), Axe secondaire = vertical (haut-bas)
mainAxisAlignment et crossAxisAlignment fonctionnent de la même manière.
Si vous mettez trop d'éléments dans une
Row, ils peuvent dépasser de l'écran (débordement). Flutter affichera une erreur. Nous verrons comment gérer cela dans la prochaine section.
💡 Points clés à retenir
Roworganise les widgets horizontalement (de gauche à droite)- Il utilise
children: []pour accepter plusieurs widgets - Pour
Row, l'axe principal est horizontal (contrairement àColumn) mainAxisAlignmentcontrôle l'alignement horizontalcrossAxisAlignmentcontrôle l'alignement vertical
Dans la section suivante, nous allons apprendre à combiner
Row et Column pour créer des interfaces plus complexes et structurées.
2.4.4 – Combiner Row et Column
Maintenant que vous connaissez Column et Row, vous pouvez les combiner pour créer des interfaces plus complexes. C'est une technique très puissante en Flutter.
🏗️ Construire des interfaces plus riches
En combinant Row et Column, vous pouvez créer des grilles, des tableaux, et des layouts complexes. Par exemple, vous pouvez avoir une Column qui contient plusieurs Row, ou une Row qui contient plusieurs Column.
Imaginez une carte de contact avec un nom, un email et un téléphone. Vous pourriez avoir :
- Une
Columnprincipale qui contient toutes les informations - Chaque ligne d'information pourrait être une
Rowavec une icône à gauche et le texte à droite
Row et Column.
🧪 Exemple : Column contenant des Row
Voici un exemple simple où une Column contient plusieurs Row :
import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Mon Application'),
),
body: SafeArea(
child: Center(
child: Column(
children: [
Row(
children: [
Text('Ligne 1 - Élément 1'),
Text('Ligne 1 - Élément 2'),
],
),
Row(
children: [
Text('Ligne 2 - Élément 1'),
Text('Ligne 2 - Élément 2'),
],
),
],
),
),
),
),
);
}
}
Dans cet exemple :
- La
Columnprincipale organise deuxRowverticalement - Chaque
Rowcontient deux textes côte à côte - Le résultat est une grille simple de 2 lignes et 2 colonnes
⚠️ Attention aux débordements
Quand vous utilisez Row ou Column, il faut faire attention aux débordements. Si vous mettez trop d'éléments ou des éléments trop larges, ils peuvent dépasser de l'écran.
Si vous voyez une erreur comme "RenderFlex overflowed", cela signifie qu'un
Row ou Column a trop de contenu pour tenir dans l'espace disponible. Pour l'instant, utilisez peu d'éléments ou des éléments courts pour éviter ce problème.
Pour éviter les débordements, vous pouvez :
- Utiliser moins d'éléments dans vos
RowouColumn - Utiliser des textes plus courts
- Envelopper votre
RowouColumndans unSingleChildScrollView(nous verrons cela plus tard)
📏 Utiliser Expanded() pour répartir l'espace
Le widget Expanded est une solution élégante pour éviter les débordements et répartir l'espace disponible dans une Row ou une Column. Il permet à un widget enfant de prendre tout l'espace disponible qui reste après que les autres enfants aient pris leur place.
Imaginez une table avec plusieurs personnes. Si certaines personnes prennent une place fixe,
Expanded permet aux autres de se partager équitablement l'espace restant. C'est comme un "étirement" intelligent qui s'adapte à l'espace disponible.
Comment fonctionne Expanded ?
Expanded enveloppe un widget et lui permet de prendre tout l'espace disponible le long de l'axe principal (horizontal pour Row, vertical pour Column).
Voici un exemple avec une Row :
Row(
children: [
Container(
width: 100,
height: 50,
color: Colors.red,
),
Expanded(
child: Container(
height: 50,
color: Colors.blue,
),
),
Container(
width: 100,
height: 50,
color: Colors.green,
),
],
)
Dans cet exemple :
- Le premier
Containerrouge a une largeur fixe de 100 pixels - Le
Containerbleu est enveloppé dansExpanded: il prendra tout l'espace horizontal restant - Le dernier
Containervert a aussi une largeur fixe de 100 pixels
Expanded ne peut être utilisé que comme enfant direct d'une Row, Column, ou Flex (un widget parent de Row et Column). Il ne fonctionne pas dans d'autres contextes.
Exemple complet avec Expanded
Voici un exemple complet qui montre une structure classique avec des zones Top, Left, Center, Right et Bottom. Cet exemple illustre l'utilisation de Expanded à la fois dans une Column et dans une Row :
Column, Row et Expanded : la zone centrale occupe tout l’espace restant, encadrée par des zones latérales fixes.
import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(title: const Text('Structure Top - Left - Right - Bottom - Center')),
body: SafeArea(
child: Column(
children: [
// 🔵 TOP
Container(
color: Colors.blue[100],
padding: const EdgeInsets.all(16),
width: double.infinity,
child: const Text("ZONE TOP", textAlign: TextAlign.center),
),
// 🔵 CENTER avec Left / Center / Right
Expanded(
child: Row(
children: [
// 🔹 LEFT
Container(
width: 80,
color: Colors.green[100],
child: const Center(child: Text("LEFT")),
),
// 🔹 CENTER
Expanded(
child: Container(
color: Colors.grey[200],
child: const Center(child: Text("CENTER")),
),
),
// 🔹 RIGHT
Container(
width: 80,
color: Colors.red[100],
child: const Center(child: Text("RIGHT")),
),
],
),
),
// 🔵 BOTTOM
Container(
color: Colors.yellow[200],
padding: const EdgeInsets.all(16),
width: double.infinity,
child: const Text("ZONE BOTTOM", textAlign: TextAlign.center),
),
],
),
),
),
);
}
}
Analysons la structure de cet exemple :
- ZONE TOP : Un
Containerbleu en haut avecwidth: double.infinitypour prendre toute la largeur disponible - ZONE CENTER : Un
Expandedqui contient uneRowavec trois zones :- LEFT : Container vert de 80 pixels de largeur fixe
- CENTER : Container gris enveloppé dans
Expandedqui prend tout l'espace horizontal restant - RIGHT : Container rouge de 80 pixels de largeur fixe
- ZONE BOTTOM : Un
Containerjaune en bas avecwidth: double.infinitypour prendre toute la largeur
double.infinity: Une valeur spéciale qui signifie "toute la largeur disponible". C'est utile pour faire prendre toute la largeur à un widget dans uneColumn.textAlign: TextAlign.center: Centre le texte horizontalement dans son widget parent.Colors.blue[100]: Utilise une nuance claire de bleu (comme expliqué dans la section sur Container).padding: EdgeInsets.all(16): Ajoute 16 pixels d'espace à l'intérieur du container.
Dans cet exemple,
Expanded est utilisé deux fois :
- Dans la Column : Le
Expandedqui enveloppe laRowpermet à la zone centrale de prendre tout l'espace vertical disponible entre TOP et BOTTOM. - Dans la Row : Le
Expandedqui enveloppe le container CENTER permet à cette zone de prendre tout l'espace horizontal disponible entre LEFT et RIGHT.
Expandedpermet à un widget de prendre l'espace disponible- Il fonctionne uniquement dans
RowouColumn - Il évite les débordements en s'adaptant à l'espace disponible
- Plusieurs
Expandedse partagent équitablement l'espace restant
📊 Utiliser flex pour contrôler la répartition de l'espace
Par défaut, tous les widgets Expanded dans une Row ou Column se partagent équitablement l'espace disponible. Mais vous pouvez contrôler cette répartition en utilisant le paramètre flex.
Le paramètre
flex définit la proportion d'espace que chaque Expanded doit recevoir. Plus la valeur de flex est grande, plus le widget prendra d'espace.
Voici un exemple avec deux Expanded ayant des valeurs de flex différentes :
Row(
children: [
Expanded(
flex: 2,
child: Container(color: Colors.red),
),
Expanded(
flex: 1,
child: Container(color: Colors.blue),
),
],
)
Analysons ce code :
Expanded(flex: 2, ...): Le container rouge prendra 2 parts de l'espace disponibleExpanded(flex: 1, ...): Le container bleu prendra 1 part de l'espace disponible- Résultat : Le rouge prendra 2/3 de l'espace (2 parts sur 3 au total) et le bleu prendra 1/3 (1 part sur 3)
Pour calculer la proportion d'espace que chaque widget reçoit :
- Additionnez toutes les valeurs de
flex: ici 2 + 1 = 3 - Divisez chaque valeur de
flexpar cette somme - Rouge : 2 ÷ 3 = 66,7% de l'espace
- Bleu : 1 ÷ 3 = 33,3% de l'espace
🧪 Exemple complet : Expanded avec flex
Voici un exemple complet qui montre l'utilisation de flex :
Expanded dans une Row avec des valeurs de flex différentes : rouge (2 parts), bleu (1 part).
import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Expanded avec flex'),
),
body: SafeArea(
child: Row(
children: [
Expanded(
flex: 2,
child: Container(
color: Colors.red,
child: const Center(
child: Text(
'flex: 2\n(66,7%)',
style: TextStyle(color: Colors.white, fontSize: 18),
),
),
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.blue,
child: const Center(
child: Text(
'flex: 1\n(33,3%)',
style: TextStyle(color: Colors.white, fontSize: 18),
),
),
),
),
],
),
),
),
);
}
}
Dans cet exemple, le container rouge prend deux fois plus d'espace que le container bleu. Si vous changez les valeurs de flex, les proportions changeront automatiquement.
Voici quelques exemples de proportions courantes :
flex: 1etflex: 1→ 50% / 50% (égal)flex: 2etflex: 1→ 66,7% / 33,3% (2:1)flex: 3etflex: 1→ 75% / 25% (3:1)flex: 1,flex: 1,flex: 1→ 33,3% / 33,3% / 33,3% (égal pour 3)
- Si vous ne spécifiez pas
flex, la valeur par défaut est1 - Les valeurs de
flexdoivent être des nombres entiers positifs (1, 2, 3, etc.) - Plusieurs
Expandedsansflexse partagent équitablement l'espace (comme si tous avaientflex: 1)
2.4.5 – Présenter du contenu avec Card
Pour finir ce chapitre, découvrons Card, un widget qui permet de présenter du contenu de manière élégante. Les cartes sont très utilisées dans les applications modernes pour organiser l'information.
🎴 Pourquoi Card ?
Card est un widget qui affiche son contenu dans une carte avec :
- Un fond légèrement surélevé (effet d'ombre)
- Des coins arrondis
- Un espacement interne (padding) automatique
- Une apparence professionnelle et moderne
Card mettant en valeur du contenu.
Les cartes sont partout dans les applications modernes. Par exemple, dans une application de météo, chaque prévision est souvent affichée dans une carte. Dans une application de nouvelles, chaque article est dans une carte. C'est un moyen élégant d'organiser l'information.
📝 Exemple minimal : Card + Padding + Text
Voici un exemple simple avec Card et Text :
Card(
child: Text('Contenu de la carte'),
)
Pour améliorer l'apparence, nous pouvons ajouter du padding (espacement interne) avec le widget Padding :
Card(
child: Padding(
padding: EdgeInsets.all(16),
child: Text('Contenu de la carte'),
),
)
Analysons ce code :
Cardcrée la carte avec son style par défautPaddingajoute de l'espace autour du textepadding: EdgeInsets.all(16)ajoute 16 pixels d'espace de tous les côtésTextaffiche le contenu
- Padding : Espace à l'intérieur d'un widget (entre le bord et le contenu)
- Margin : Espace à l'extérieur d'un widget (entre le widget et les autres éléments)
Card, on utilise généralement Padding à l'intérieur pour espacer le contenu des bords de la carte.
🧪 Exemple complet
Voici un exemple complet dans une application :
Card contenant du texte avec du Padding.
import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Mon Application'),
),
body: SafeArea(
child: Center(
child: Card(
child: Padding(
padding: EdgeInsets.all(16),
child: Text('Bonjour Flutter !'),
),
),
),
),
),
);
}
}
Dans cet exemple, le texte "Bonjour Flutter !" est affiché dans une carte élégante avec un espacement interne.
📦 Card utilisée dans une Column ou Row
Les cartes sont souvent utilisées dans des Column ou Row pour créer des listes de cartes. Voici un exemple avec une Column :
Card empilées verticalement dans une Column.
import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Mon Application'),
),
body: SafeArea(
child: Center(
child: Column(
children: [
Card(
child: Padding(
padding: EdgeInsets.all(16),
child: Text('Première carte'),
),
),
Card(
child: Padding(
padding: EdgeInsets.all(16),
child: Text('Deuxième carte'),
),
),
Card(
child: Padding(
padding: EdgeInsets.all(16),
child: Text('Troisième carte'),
),
),
],
),
),
),
),
);
}
}
Dans cet exemple, trois cartes sont affichées verticalement dans une Column. Chaque carte contient du texte avec du padding.
Pour espacer les cartes entre elles, vous pouvez ajouter des marges aux cartes ou utiliser
mainAxisAlignment: MainAxisAlignment.spaceBetween dans la Column. Pour l'instant, gardons les choses simples.
💡 Points clés à retenir
Cardprésente le contenu de manière élégante avec des ombres et des coins arrondisPaddingajoute de l'espace à l'intérieur d'un widget- Les cartes sont souvent utilisées dans des
ColumnouRowpour créer des listes EdgeInsets.all(16)ajoute 16 pixels d'espace de tous les côtés
Dans la section suivante, nous allons découvrir
SizedBox, un widget simple mais très utile pour ajouter de l'espacement entre les éléments.
2.4.6 – Gérer l'espacement avec Padding et SizedBox
Quand vous organisez plusieurs widgets dans une Column ou une Row, il est souvent nécessaire d'ajouter de l'espace. Flutter propose deux widgets pour cela : Padding et SizedBox. Chacun a son utilité et ses cas d'usage. Découvrons-les ensemble.
📦 Introduction à Padding
Padding est un widget qui ajoute de l'espace autour d'un widget existant. Il enveloppe un widget et ajoute de l'espacement à l'intérieur, entre le bord et le contenu.
Imaginez une boîte avec un objet à l'intérieur.
Padding est comme ajouter de la mousse autour de l'objet pour qu'il ne touche pas les bords de la boîte. L'espace est créé autour de l'objet, à l'intérieur de la boîte.
Voici la structure de base de Padding :
Padding(
padding: EdgeInsets.all(16),
child: Text('Mon texte'),
)
Analysons ce code :
Padding(: Le widget qui ajoute de l'espacepadding: EdgeInsets.all(16): Ajoute 16 pixels d'espace de tous les côtés (haut, bas, gauche, droite)child: Text('Mon texte'): Le widget autour duquel l'espace est ajouté
EdgeInsets.all(16) ajoute 16 pixels d'espace de tous les côtés. Vous pouvez aussi utiliser :
EdgeInsets.only(left: 10, top: 20): espace spécifique sur certains côtésEdgeInsets.symmetric(horizontal: 16, vertical: 8): espace symétrique
EdgeInsets.all() est le plus simple et le plus courant.
📏 Introduction à SizedBox
SizedBox est un widget qui crée un espace vide de taille définie. Contrairement à Padding, il ne contient pas de widget enfant : c'est un espace vide qui prend de la place.
Imaginez que vous rangez des livres sur une étagère.
SizedBox est comme un espace vide entre deux livres. Il ne contient rien, mais il crée une séparation visuelle entre les éléments.
Voici la structure de base de SizedBox :
SizedBox(height: 20)
Pour un espace vertical, utilisez height. Pour un espace horizontal, utilisez width.
SizedBox est très simple : il crée un espace vide. Il n'a pas besoin de child car il ne contient rien. C'est juste un espace qui prend de la place dans votre layout.
⬆️ Exemples d'espacement vertical
Pour ajouter de l'espace vertical entre des éléments dans une Column, vous pouvez utiliser les deux méthodes :
Avec SizedBox
Column(
children: [
Text('Premier élément'),
SizedBox(height: 20), // Espace vide entre les deux textes
Text('Deuxième élément'),
],
)
SizedBox(height: 20) crée un espace vertical de 20 pixels entre les deux textes.
Avec Padding
Column(
children: [
Padding(
padding: EdgeInsets.only(bottom: 20), // Espace en bas du premier texte
child: Text('Premier élément'),
),
Text('Deuxième élément'),
],
)
Padding avec EdgeInsets.only(bottom: 20) ajoute 20 pixels d'espace en bas du premier texte.
EdgeInsets.only() permet de définir l'espace sur un seul côté. Ici, bottom: 20 ajoute 20 pixels d'espace uniquement en bas. Vous pouvez aussi utiliser top, left, ou right.
➡️ Exemples d'espacement horizontal
Pour ajouter de l'espace horizontal entre des éléments dans une Row, vous pouvez aussi utiliser les deux méthodes :
Avec SizedBox
Row(
children: [
Text('Premier'),
SizedBox(width: 30), // Espace vide entre les deux textes
Text('Deuxième'),
],
)
SizedBox(width: 30) crée un espace horizontal de 30 pixels entre les deux textes.
Avec Padding
Row(
children: [
Padding(
padding: EdgeInsets.only(right: 30), // Espace à droite du premier texte
child: Text('Premier'),
),
Text('Deuxième'),
],
)
Padding avec EdgeInsets.only(right: 30) ajoute 30 pixels d'espace à droite du premier texte.
🧪 Exemple complet : espacement vertical avec SizedBox
Voici un exemple complet avec espacement vertical dans une Column utilisant SizedBox :
SizedBox entre chaque texte dans une Column.
import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Mon Application'),
),
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Premier élément',
style: TextStyle(fontSize: 20),
),
const SizedBox(height: 30),
const Text(
'Deuxième élément',
style: TextStyle(fontSize: 20),
),
const SizedBox(height: 30),
const Text(
'Troisième élément',
style: TextStyle(fontSize: 20),
),
],
),
),
),
),
);
}
}
Dans cet exemple, les trois textes sont séparés par des espaces de 30 pixels chacun, le tout centré à l'écran.
Les valeurs d'espacement les plus courantes sont :
SizedBox(height: 8)ouwidth: 8: espacement très petitSizedBox(height: 16)ouwidth: 16: espacement petitSizedBox(height: 24)ouwidth: 24: espacement moyenSizedBox(height: 32)ouwidth: 32: espacement grand
🧪 Exemple complet : espacement horizontal avec SizedBox
Voici un exemple avec espacement horizontal dans une Row utilisant SizedBox :
import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Mon Application'),
),
body: SafeArea(
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Premier',
style: TextStyle(fontSize: 20),
),
const SizedBox(width: 40),
const Text(
'Deuxième',
style: TextStyle(fontSize: 20),
),
const SizedBox(width: 40),
const Text(
'Troisième',
style: TextStyle(fontSize: 20),
),
],
),
),
),
),
);
}
}
Dans cet exemple, les trois textes sont séparés horizontalement par des espaces de 40 pixels chacun.
🔄 Comparatif : SizedBox ou Padding ?
Maintenant que vous connaissez les deux widgets, vous vous demandez peut-être : lequel utiliser et quand ? Voici un comparatif clair pour vous aider à choisir.
SizedBox: Crée un espace vide, un widget invisible qui prend de la place. Il est utilisé pour espacer des éléments entre eux dans une liste.Padding: Ajoute de l'espace autour d'un widget existant. Il enveloppe un widget et ajoute de l'espacement à l'intérieur, entre le bord et le contenu.
Exemple visuel de la différence
Voici deux exemples qui montrent la différence :
// Avec SizedBox : espace ENTRE les éléments
Column(
children: [
Text('Premier'),
SizedBox(height: 20), // Espace vide entre les deux textes
Text('Deuxième'),
],
)
// Avec Padding : espace AUTOUR d'un élément
Column(
children: [
Padding(
padding: EdgeInsets.all(20), // Espace autour du texte
child: Text('Premier'),
),
Text('Deuxième'),
],
)
Il y a un espace vide de 20 pixels entre les deux textes. Le
SizedBox est un élément séparé dans la liste.
L'espace de 20 pixels est autour du premier texte. Le
Padding enveloppe le texte et crée de l'espace à l'intérieur.
Quand utiliser quoi ?
SizedBox quand :- Vous voulez espacer des éléments entre eux dans une
Columnou uneRow - Vous avez besoin d'un espacement simple et clair
- Vous voulez séparer visuellement plusieurs widgets dans une liste
Column avec SizedBox(height: 16) entre chacun.
Padding quand :- Vous voulez ajouter de l'espace autour d'un widget spécifique
- Vous travaillez avec un widget qui a besoin d'espace interne (comme une
Card) - Vous voulez créer une zone de "respiration" autour d'un contenu
Card avec Padding(padding: EdgeInsets.all(16), child: Text(...)).
Dans la plupart des cas, pour espacer des éléments dans une
Column ou une Row, utilisez SizedBox. C'est plus simple, plus clair et plus direct. Utilisez Padding quand vous voulez vraiment ajouter de l'espace autour d'un widget spécifique, comme nous l'avons fait avec les Card dans la section précédente.
💡 Points clés à retenir
Paddingajoute de l'espace autour d'un widget existantPaddingutiliseEdgeInsets.all(16)pour ajouter de l'espace de tous les côtésSizedBoxcrée un espace vide de taille définieSizedBox(height: 20)crée un espace vertical de 20 pixelsSizedBox(width: 30)crée un espace horizontal de 30 pixelsSizedBoxest utilisé pour espacer des éléments entre eux dans une listePaddingest utilisé pour ajouter de l'espace autour d'un widget spécifique
Voici les structures principales :
// Padding : espace autour d'un widget
Padding(
padding: EdgeInsets.all(16),
child: Text('Mon texte'),
)
// SizedBox : espace entre les éléments
SizedBox(height: 20) // Vertical
SizedBox(width: 30) // Horizontal
Choisissez selon votre besoin : espace autour d'un widget → Padding, espace entre des éléments → SizedBox.
Dans la section suivante, nous allons découvrir
Divider, un widget simple mais très utile pour séparer visuellement des éléments dans votre interface.
2.4.7 – Séparer visuellement avec Divider
Quand vous organisez plusieurs éléments dans une Column ou une Row, il est parfois utile de les séparer visuellement avec une ligne. Le widget Divider est parfait pour cela. C'est un widget simple qui affiche une ligne horizontale pour séparer des éléments.
📏 Rôle du Divider
Divider est un widget qui affiche une ligne horizontale fine. Il est utilisé pour séparer visuellement des éléments dans une interface, créant une distinction claire entre différentes sections ou groupes d'informations.
Imaginez un menu de restaurant. Les différentes sections (entrées, plats principaux, desserts) sont souvent séparées par des lignes horizontales.
Divider fonctionne de la même manière : il crée une séparation visuelle claire entre des groupes d'éléments.
🧪 Exemple simple : Divider entre deux widgets
Voici comment utiliser Divider dans une Column :
Column(
children: [
Text('Premier élément'),
Divider(),
Text('Deuxième élément'),
],
)
Dans cet exemple, Divider() crée une ligne horizontale entre les deux textes.
Divider() est très simple à utiliser : il ne nécessite aucun paramètre. Par défaut, il affiche une ligne horizontale fine avec un espacement automatique de chaque côté.
🧪 Exemple complet : Divider dans une Column
Voici un exemple complet dans une application :
Divider() sépare deux widgets dans une Column.
import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Mon Application'),
),
body: SafeArea(
child: Column(
children: [
const Padding(
padding: EdgeInsets.all(16),
child: Text('Section 1', style: TextStyle(fontSize: 20)),
),
const Divider(),
const Padding(
padding: EdgeInsets.all(16),
child: Text('Section 2', style: TextStyle(fontSize: 20)),
),
const Divider(),
const Padding(
padding: EdgeInsets.all(16),
child: Text('Section 3', style: TextStyle(fontSize: 20)),
),
],
),
),
),
);
}
}
Dans cet exemple, trois sections de texte sont séparées par des Divider, créant une interface claire et organisée.
🎨 Personnalisation (épaisseur, couleur, marges)
Vous pouvez personnaliser l'apparence du Divider avec plusieurs paramètres :
Divider(
height: 20,
thickness: 2,
color: Colors.grey,
indent: 20,
endIndent: 20,
)
Analysons ces paramètres :
height: 20: La hauteur totale du Divider (espace vertical qu'il occupe, en pixels)thickness: 2: L'épaisseur de la ligne (en pixels). Par défaut, c'est 1 pixelcolor: Colors.grey: La couleur de la ligne. Par défaut, c'est une couleur grise claireindent: 20: L'espacement à gauche de la ligne (en pixels)endIndent: 20: L'espacement à droite de la ligne (en pixels)
Ces paramètres permettent de créer une ligne qui ne va pas d'un bord à l'autre. Par exemple,
indent: 20 et endIndent: 20 créent une ligne qui commence 20 pixels après le bord gauche et se termine 20 pixels avant le bord droit.
🧪 Exemple complet : Divider personnalisé
Voici un exemple avec un Divider personnalisé :
Divider personnalisé sépare deux sections avec couleur, épaisseur, et marges définies.
import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Mon Application'),
),
body: SafeArea(
child: Column(
children: [
const Padding(
padding: EdgeInsets.all(16),
child: Text('Première section', style: TextStyle(fontSize: 20)),
),
const Divider(
height: 30,
thickness: 2,
color: Colors.blue,
indent: 40,
endIndent: 40,
),
const Padding(
padding: EdgeInsets.all(16),
child: Text('Deuxième section', style: TextStyle(fontSize: 20)),
),
],
),
),
),
);
}
}
Dans cet exemple, le Divider est personnalisé avec une épaisseur de 2 pixels, une couleur bleue, et des espacements à gauche et à droite de 40 pixels.
💼 Cas d'utilisation courants
Divider est très utile dans plusieurs situations :
Dans une
Column contenant plusieurs sections d'informations, Divider permet de créer une séparation visuelle claire entre chaque section.
Vous pouvez utiliser
Divider à l'intérieur d'une Card pour séparer différents types d'informations (par exemple, un titre, un Divider, puis le contenu).
Dans une interface de menu ou de navigation,
Divider permet de séparer visuellement les différents groupes d'options.
🧪 Exemple : Divider dans une Card
Voici un exemple d'utilisation de Divider dans une Card :
Divider utilisé pour séparer le titre et le contenu dans une Card.
import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Mon Application'),
),
body: SafeArea(
child: Center(
child: Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Padding(
padding: EdgeInsets.all(16),
child: Text(
'Titre de la carte',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
const Divider(),
const Padding(
padding: EdgeInsets.all(16),
child: Text('Contenu de la carte'),
),
],
),
),
),
),
),
);
}
}
Dans cet exemple, une Card contient un titre, un Divider, puis le contenu. Le Divider sépare visuellement le titre du contenu.
Ce paramètre de
Column fait que la colonne prend seulement l'espace nécessaire (minimum) au lieu de prendre tout l'espace disponible. C'est utile dans une Card pour que la carte ne soit pas trop grande.
💡 Points clés à retenir
Divideraffiche une ligne horizontale pour séparer visuellement des élémentsDivider()est très simple à utiliser sans paramètresheightdéfinit l'espace vertical total occupé par le Dividerthicknessdéfinit l'épaisseur de la ligne (par défaut : 1 pixel)colordéfinit la couleur de la ligneindentetendIndentcréent des espacements à gauche et à droiteDividerest souvent utilisé dans des listes, des Card, ou des menus
Voici les utilisations principales de
Divider :
// Divider simple
Divider()
// Divider personnalisé
Divider(
height: 20,
thickness: 2,
color: Colors.grey,
indent: 20,
endIndent: 20,
)
Utilisez Divider pour créer des séparations visuelles claires dans votre interface.
Vous avez terminé ce chapitre ! Vous savez maintenant :
- ✅ Utiliser
Containerpour styliser et organiser - ✅ Organiser des widgets verticalement avec
Column - ✅ Organiser des widgets horizontalement avec
Row - ✅ Combiner
RowetColumnpour des layouts complexes - ✅ Utiliser
Expandedpour répartir l'espace - ✅ Présenter du contenu avec
Card - ✅ Gérer l'espacement avec
PaddingetSizedBox - ✅ Séparer visuellement avec
Divider
Vous avez appris à organiser votre interface Flutter :
- ✅
Containerpermet de styliser avec taille, couleur et marges - ✅
Columnorganise les widgets verticalement - ✅
Roworganise les widgets horizontalement - ✅
children: []permet d'ajouter plusieurs widgets - ✅
mainAxisAlignmentetcrossAxisAlignmentcontrôlent l'alignement - ✅
Expandedpermet de répartir l'espace disponible - ✅
Cardprésente le contenu de manière élégante - ✅
Paddingajoute de l'espace interne - ✅
SizedBoxpermet d'espacer des éléments entre eux - ✅
Dividersépare visuellement des éléments