Le Tutoriel de Flutter Row
1. Row
Row est un widget qui affiche ses widgets enfants sur une ligne. Une autre variante est Column qui montre ses widgets enfants sur une colonne.
Pour que le widget enfant de Row s'ouvre pour remplir l'espace horizontal disponible, vous pouvez l'envelopper dans un objet Expanded.
Row place ses enfants sur une ligne et ne peut pas se défiler. Si vous souhaitez obtenir un conteneur similaire et défilable, vous pouvez utiliser ListView.
Row Constructor:
Row Constructor
Row(
{Key key,
List<Widget> children: const <Widget>[],
MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start,
MainAxisSize mainAxisSize: MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center,
TextDirection textDirection,
VerticalDirection verticalDirection: VerticalDirection.down,
TextBaseline textBaseline: TextBaseline.alphabetic
}
)
2. children
La propriété children est utilisée pour définir une liste des widgets enfants de Row.
Vous pouvez ajouter des widgets enfants à children ou supprimer des widgets de children, mais vous devez suivre la règle mentionnée dans la section "Add/Remove Children".
List<Widget> children: const <Widget>[]
À commencer par le premier exemple, une Row avec quatre widgets enfants:
main.dart (children ex1)
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'o7planning.org',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Flutter Row Example")
),
body: Center(
child: Row (
children: [
ElevatedButton(child: Text("BTN 1"), onPressed:(){}),
Icon(Icons.ac_unit, size: 64, color: Colors.blue),
ElevatedButton(
child: Text("Button 2"),
onPressed:(){},
style: ButtonStyle(
minimumSize: MaterialStateProperty.all(Size.square(100))
)
),
ElevatedButton(child: Text("BTN 3"), onPressed:(){}),
]
)
),
);
}
}
Certains widgets enfants avec flex> 0 sont capables d'étendre sa largeur pour remplir l'espace restant horizontalement comme Expanded et Spacer, etc. Ils sont souvent utilisés pour ajuster la distance entre les widgets enfants de Row. Ci-dessous un exemple:
children (ex2)
Row (
children: [
ElevatedButton(child: Text("BTN 1"), onPressed:(){}),
Expanded(
flex: 1,
child: Icon(Icons.ac_unit, size: 64, color: Colors.blue),
),
ElevatedButton(
child: Text("Button 2"),
onPressed:(){},
style: ButtonStyle(
minimumSize: MaterialStateProperty.all(Size.square(100))
)
),
Spacer(
flex: 2
),
ElevatedButton(child: Text("BTN 3"), onPressed:(){}),
]
)
3. Add/Remove children
Vous pouvez ajouter quelques widgets enfants à une Row ou en supprimer certains de Row. Suivre l'instruction ci-dessous peut conduire à des résultats inattendus:
** Not Working! **
class SomeWidgetState extends State<SomeWidget> {
List<Widget> _children;
void initState() {
_children = [];
}
void someHandler() {
setState(() {
_children.add(newWidget);
});
}
Widget build(BuildContext context) {
// Reusing `List<Widget> _children` here is problematic.
return Row(children: this._children);
}
}
Pour résoudre le problème ci-dessus, vous devez respecter les règles suivantes:
- Les widgets enfants doivent se voir explicitement attribuer une valeur Key, ce qui aide Flutter à reconnaître les anciens ou les nouveaux widgets enfants lorsque le nombre de widgets change.
- Un nouvel objet List doit être créé pour Row.children si un certain widget enfant change, ou le nombre de widgets enfants change.
** Worked! **
class SomeWidgetState extends State<SomeWidget> {
List<Widget> _children;
void initState() {
this._children = [];
}
// Add or remove some children..
void someHandler() {
setState(() {
// The key here allows Flutter to reuse the underlying render
// objects even if the children list is recreated.
this._children.add(newWidget(key: ...));
});
}
Widget build(BuildContext context) {
// Always create a new list of children as a Widget is immutable.
var newChildren = List.from(this._children);
this._children = newChildren;
return Row(children: this._children);
}
}
Par exemple:
main.dart (children ex3)
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'o7planning.org',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
State<StatefulWidget> createState() {
return MyHomePageState();
}
}
class MyHomePageState extends State<MyHomePage> {
List<Widget> _children = [];
int idx = 0;
@override
void initState() {
super.initState();
this._children = [
ElevatedButton(
key: Key(this.idx.toString()),
child: Text("Btn " + idx.toString()),
onPressed: (){}
)
];
}
void addChildHandler() {
this.idx++;
this.setState(() {
var newChild = ElevatedButton(
key: Key(this.idx.toString()),
child: Text("Btn " + idx.toString()),
onPressed: (){}
);
this._children.add(newChild);
});
}
@override
Widget build(BuildContext context) {
// Create new List object:
this._children = this._children == null? [] : List.from(this._children);
return Scaffold(
appBar: AppBar(
title: Text("Flutter Row Example")
),
body: Center(
child: Row (
children: this._children
)
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
this.addChildHandler();
}
),
);
}
}
4. mainAxisAlignment
La propriété mainAxisAlignment est utilisée pour spécifier la manière dont les widgets enfants seront organisés sur l'axe principal. Quant à Row, l'axe principal est l'axe horizontal principal.
MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start
// MainAxisAlignment enum:
MainAxisAlignment.start
MainAxisAlignment.center
MainAxisAlignment.end
MainAxisAlignment.spaceBetween
MainAxisAlignment.spaceAround
MainAxisAlignment.spaceEvenly
MainAxisAlignment.start
Au cas où textDirection = TextDirection.ltr (par défaut) et mainAxisAlignment = MainAxisAlignment.start, les widgets enfants de Row seront placés côte à côte de gauche à droite.
MainAxisAlignment.start
Row (
mainAxisAlignment: MainAxisAlignment.start,
children: [
ElevatedButton(child: Text("Button 1"), onPressed:(){}),
ElevatedButton(
child: Text("Button 2"),
onPressed:(){},
style: ButtonStyle(
minimumSize: MaterialStateProperty.all(Size.square(100))
)
),
ElevatedButton(child: Text("Very Long Button 3"), onPressed:(){})
]
)
MainAxisAlignment.center
mainAxisAlignment: MainAxisAlignment.center
MainAxisAlignment.end
Au cas où textDirection = TextDirection.ltr (par défaut) et mainAxisAlignment = MainAxisAlignment.end, les widgets enfants de Row seront placés côte à côte de droite à gauche.
mainAxisAlignment: MainAxisAlignment.end
MainAxisAlignment.spaceBetween
mainAxisAlignment: MainAxisAlignment.spaceBetween
MainAxisAlignment.spaceEvenly
mainAxisAlignment: MainAxisAlignment.spaceEvenly
MainAxisAlignment.spaceAround
mainAxisAlignment: MainAxisAlignment.spaceAround
5. mainAxisSize
La propriété mainAxisSize spécifie la quantité d'espace vertical devant être occupée par Row. Sa valeur par défaut est MainAxisSize.max, ce qui signifie que Row essaie d'occuper le plus d'espace horizontal possible.
S'il y a un widget enfant avec "flex> 0 && fit! = FlexFit.loose", Row essayera de prendre le plus d'espace possible, quelle que soit la valeur de mainAxisSize.
À l'inverse, si mainAxisSize = MainAxisSize.min, Row aura une largeur suffisante pour tous ses widgets enfants.
MainAxisSize mainAxisSize: MainAxisSize.max
// MainAxisSize enum:
MainAxisSize.max
MainAxisSize.min
6. crossAxisAlignment
La propriété crossAxisAlignment est utilisée pour spécifier la manière dont les widgets enfants seront disposés sur l'axe transversal. Quant à Row, l'axe transversal est l'axe vertical.
CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center
// CrossAxisAlignment enum:
CrossAxisAlignment.start
CrossAxisAlignment.end
CrossAxisAlignment.center
CrossAxisAlignment.baseline
CrossAxisAlignment.stretch
CrossAxisAlignment.start
Au cas où verticalDirection = VerticalDirection.down (par défaut) et crossAxisAlignment = CrossAxisAlignment.start, les widgets enfants de Row seront placés près du bord supérieur de Row.
CrossAxisAlignment.start
Row (
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ElevatedButton(child: Text("Button 1"), onPressed:(){}),
ElevatedButton(
child: Text("Button 2"),
onPressed:(){},
style: ButtonStyle(
minimumSize: MaterialStateProperty.all(Size.square(100))
)
),
ElevatedButton(child: Text("Very Long Button 3"), onPressed:(){})
]
)
CrossAxisAlignment.center (Default).
crossAxisAlignment: CrossAxisAlignment.center
CrossAxisAlignment.end
Au cas où verticalDirection = VerticalDirection.down (par défaut) et crossAxisAlignment = CrossAxisAlignment.end, les widgets enfants de Row seront placés près du bord inférieur de Row.
crossAxisAlignment: CrossAxisAlignment.end
CrossAxisAlignment.stretch
crossAxisAlignment: CrossAxisAlignment.stretch
CrossAxisAlignment.baseline
crossAxisAlignment: CrossAxisAlignment.baseline
Par exemple:
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic
7. textDirection
La propriété textDirection spécifie la manière dont les widgets enfants de Row seront disposés sur l'axe principal (axe horizontal) et celle dont les mots "start" et "end" sont interprétés.
TextDirection textDirection
// TextDirection enum:
TextDirection.ltr (Left to Right) (Default)
TextDirection.rtl (Right to Left)
Si textDirection = TextDirection.ltr (par défaut), le mot "start" correspondra à "left" et le mot "end" correspondra à "right".
En revanche, au cas où textDirection = TextDirection.rtl, le mot "start" correspondra à "right" et le mot "end" correspondra à "left".
8. verticalDirection
La propriété verticalDirection spécifie comment les widgets enfants de Row seront disposés sur l'axe transversal (axe vertical) et comment les mots "start" et "end" sont interprétés.
VerticalDirection verticalDirection: VerticalDirection.down
// VerticalDirection enum:
VerticalDirection.down (Default)
VerticalDirection.up
Au cas où verticalDirection = VerticalDirection.down (par défaut), le mot "start" correspondra à "top" et le mot "end" correspondra à "bottom".
À l'inverse, si verticalDirection = VerticalDirection.up, le mot "start" correspondra à "bottom" et le mot "end" correspondra à "top".
9. textBaseline
Si vous alignez les widgets enfants en fonction de la ligne de base (baseline), la propriété textBaseline spécifie le type de ligne de base sera utilisé.
TextBaseline textBaseline: TextBaseline.alphabetic
// TextBaseline enum:
TextBaseline.alphabetic (Default)
TextBaseline.ideographic
Par exemple:
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic
Tutoriels de programmation Flutter
- Le Tutoriel de Flutter Column
- Le Tutoriel de Flutter Stack
- Le Tutoriel de Flutter IndexedStack
- Le Tutoriel de Flutter Spacer
- Le Tutoriel de Flutter Expanded
- Le Tutoriel de Flutter SizedBox
- Le Tutoriel de Flutter Tween
- Installer Flutter SDK sur Windows
- Installer Flutter Plugin pour Android Studio
- Créez votre première application Flutter - Hello Flutter
- Le Tutoriel de Flutter Scaffold
- Le Tutoriel de Flutter AppBar
- Le Tutoriel de Flutter BottomAppBar
- Le Tutoriel de Flutter TextButton
- Le Tutoriel de Flutter ElevatedButton
- Le Tutoriel de Flutter EdgeInsetsGeometry
- Le Tutoriel de Flutter EdgeInsets
- Le Tutoriel de CircularProgressIndicator
- Le Tutoriel de Flutter LinearProgressIndicator
- Le Tutoriel de Flutter Center
- Le Tutoriel de Flutter Align
- Le Tutoriel de Flutter Row
- Le Tutoriel de Flutter SplashScreen
- Le Tutoriel de Flutter Alignment
- Le Tutoriel de Flutter Positioned
- Le Tutoriel de Flutter SimpleDialog
- Le Tutoriel de Flutter AlertDialog
- Navigation et Routing dans Flutter
- Le Tutoriel de Flutter TabBar
- Le Tutoriel de Flutter Banner
- Le Tutoriel de Flutter BottomNavigationBar
- Le Tutoriel de Flutter FancyBottomNavigation
- Le Tutoriel de Flutter Card
- Le Tutoriel de Flutter Border
- Le Tutoriel de Flutter ContinuousRectangleBorder
- Le Tutoriel de Flutter RoundedRectangleBorder
- Le Tutoriel de Flutter CircleBorder
- Le Tutoriel de Flutter StadiumBorder
- Le Tutoriel de Flutter Container
- Le Tutoriel de Flutter RotatedBox
- Le Tutoriel de Flutter CircleAvatar
- Le Tutoriel de Flutter IconButton
- Le Tutoriel de Flutter FlatButton
- Le Tutoriel de Flutter SnackBar
Show More