Aller au contenu principal

Layout

Container : Le couteau suisse des layouts

  • Description : Container est un widget polyvalent qui permet de contenir un seul widget enfant. Il offre des options de padding, de marges, de décoration (couleur, bordure, ombre), de contraintes de taille et d'alignement.
  • Exemple :
Container(
width: 200,
height: 100,
padding: const EdgeInsets.all(20),
margin: const EdgeInsets.symmetric(vertical: 10),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(10),
),
alignment: Alignment.center,
child: const Text('Contenu'),
)

Row : Disposition horizontale

  • Description : Row dispose ses widgets enfants horizontalement.
  • Propriétés importantes :
    • mainAxisAlignment : Aligne les enfants sur l'axe principal (horizontal). Les valeurs courantes sont start, end, center, spaceBetween, spaceAround, spaceEvenly.
    • crossAxisAlignment : Aligne les enfants sur l'axe transversal (vertical). Les valeurs courantes sont start, end, center, stretch, baseline.
  • Exemple :
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const [
Icon(Icons.home),
Text('Accueil'),
Icon(Icons.settings),
],
)

Column : Disposition verticale

  • Description : Column dispose ses widgets enfants verticalement.
  • Propriétés importantes : Les mêmes que pour Row, mais les axes principal et transversal sont inversés.
  • Exemple :
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text('Titre'),
Text('Sous-titre'),
],
)

Stack : Superposition de widgets

  • Description : Stack superpose ses widgets enfants. L'ordre de déclaration des enfants détermine l'ordre de superposition (le premier enfant est en bas, le dernier est en haut).
  • Positioned : Permet de positionner précisément les enfants à l'intérieur du Stack.
  • Exemple :
Stack(
alignment: Alignment.center,
children: [
Container(
width: 200,
height: 200,
color: Colors.grey[300],
),
Positioned(
top: 50,
left: 50,
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
],
)

5. Expanded et Flexible : Gestion de l'espace dans les Row et Column

  • Description : Ces widgets permettent de gérer la répartition de l'espace disponible dans un Row ou un Column.
  • Expanded : Étire le widget enfant pour occuper tout l'espace disponible. On peut utiliser la propriété flex pour donner un poids différent à plusieurs Expanded dans le même Row ou Column.
  • Flexible : Similaire à Expanded, mais le widget enfant ne s'étire pas au-delà de sa taille intrinsèque.
  • Exemple :
Row(
children: [
Expanded(
flex: 2,
child: Container(color: Colors.red),
),
Expanded(
flex: 1,
child: Container(color: Colors.blue),
),
],
)

LayoutBuilder : Adaptation à la taille de l'écran

  • Description : Permet de construire une interface utilisateur qui s'adapte à la taille de l'écran ou aux contraintes de son parent.
  • Exemple :
LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
if (constraints.maxWidth > 600) {
return Row(children: [ /* Mise en page pour les grands écrans */ ]);
} else {
return Column(children: [ /* Mise en page pour les petits écrans */ ]);
}
},
)

Dans Flutter, les BoxConstraints (contraintes de boîte) sont un concept fondamental pour comprendre comment les widgets sont dimensionnés et positionnés à l'écran. Ils définissent les limites de taille qu'un widget peut occuper. Imaginez-les comme un ensemble de règles que chaque widget doit respecter.

Qu'est-ce qu'un BoxConstraints ?

Un BoxConstraints est un objet qui spécifie les contraintes minimales et maximales de largeur et de hauteur pour un widget. Il est composé de quatre propriétés :

  • minWidth : La largeur minimale que le widget peut avoir.
  • maxWidth : La largeur maximale que le widget peut avoir.
  • minHeight : La hauteur minimale que le widget peut avoir.
  • maxHeight : La hauteur maximale que le widget peut avoir.

Comment fonctionnent les BoxConstraints ?

Le processus de layout dans Flutter fonctionne en descendant l'arbre des widgets. Chaque parent transmet des contraintes (BoxConstraints) à ses enfants. L'enfant doit ensuite se dimensionner en respectant ces contraintes.

Il existe trois types de comportements principaux pour les widgets face aux contraintes :

  1. Widgets qui essaient d'être aussi grands que possible : Certains widgets, comme Expanded, essaient d'occuper tout l'espace disponible qui leur est offert par leur parent. Ils respectent les contraintes maximales, mais ignorent les contraintes minimales.

  2. Widgets qui essaient d'être aussi petits que possible : D'autres widgets, comme Text ou Icon, essaient d'occuper le minimum d'espace nécessaire pour afficher leur contenu. Ils respectent les contraintes minimales, mais peuvent dépasser les contraintes maximales si leur contenu l'exige.

  3. Widgets qui respectent les contraintes : La plupart des widgets, comme Container sans contraintes spécifiques, essaient de respecter les contraintes minimales et maximales qui leur sont imposées. Si le widget a une taille intrinsèque (déterminée par son contenu), il essaiera de s'en approcher, tout en restant dans les limites des contraintes.

Exemples concrets :

  1. Contraintes lâches (Loose Constraints) : Si un parent donne des contraintes minWidth: 0, maxWidth: infini, minHeight: 0, et maxHeight: infini à son enfant, cela signifie que l'enfant a une grande liberté pour se dimensionner. C'est le cas par défaut pour la plupart des widgets.

  2. Contraintes strictes (Tight Constraints) : Si un parent donne des contraintes minWidth: 100, maxWidth: 100, minHeight: 50, et maxHeight: 50 à son enfant, cela signifie que l'enfant doit avoir une largeur de 100 et une hauteur de 50.

  3. Contraintes expansives (Expanding Constraints) : Le widget Expanded utilise des contraintes qui permettent à son enfant de remplir l'espace disponible dans un Row ou un Column.

Le widget ConstrainedBox :

Le widget ConstrainedBox permet d'imposer des contraintes supplémentaires à son enfant. Par exemple :

ConstrainedBox(
constraints: const BoxConstraints(
minWidth: 100,
maxWidth: 200,
minHeight: 50,
maxHeight: 100,
),
child: Container(
color: Colors.blue,
width: 50, // Cette largeur sera ignorée car elle est inférieure à minWidth
height: 150, // Cette hauteur sera limitée à maxHeight (100)
),
)

Dans cet exemple, même si le Container a une largeur de 50 et une hauteur de 150, il sera rendu avec une largeur de 100 et une hauteur de 100, car il est contraint par le ConstrainedBox.

Le widget SizedBox :

Le widget SizedBox est un cas particulier de ConstrainedBox qui permet de définir une taille fixe pour un widget :

SizedBox(
width: 100,
height: 50,
child: Container(color: Colors.red),
)

Ceci est équivalent à :

ConstrainedBox(
constraints: const BoxConstraints.tightFor(width: 100, height: 50),
child: Container(color: Colors.red),
)

Importance des BoxConstraints :

Comprendre les BoxConstraints est crucial pour :

  • Créer des layouts flexibles et adaptatifs : En utilisant les bonnes contraintes, vous pouvez faire en sorte que votre interface utilisateur s'adapte à différentes tailles d'écran et orientations d'appareil.
  • Résoudre les problèmes de layout : De nombreux problèmes de layout dans Flutter sont dus à une mauvaise compréhension des contraintes.
  • Optimiser les performances : En utilisant des contraintes appropriées, vous pouvez aider Flutter à effectuer le layout plus efficacement.

En résumé, les BoxConstraints définissent les limites de taille des widgets dans Flutter. Ils sont transmis des parents aux enfants et déterminent comment les widgets sont dimensionnés et positionnés. Une bonne compréhension de ce concept est essentielle pour maîtriser la création d'interfaces utilisateur dans Flutter.