Le Widget ListTile dans Flutter
Sommaire
- 1- Objectifs
- 2- Présentation
- 3- Composant du ListTile : Structuration d'Éléments dans une Liste
- 4- Variantes du ListTile
- 4.1-
ListTile simple
- 4.1.1- Exemple:
- 4.1.2- Exemple: Autre écriture
- 4.2-
ListTile avec interrupteur (Switch)
- 4.3-
ListTile avec sous-titre
- 4.4-
ListTile avec icône uniquement
- 4.5-
ListTile avec case à cocher
- 4.6-
ListTile avec bouton radio
- 4.7-
ListTile personnalisé
- 5- Application
- 5.1- Partie:01
- 5.2- Partie:02
- 5.3- Partie:03
- 5.4- Partie:04
- 5.4.1- Cours Flutter
Le Widget ListTile dans Flutter
-
Objectifs
- Se familiariser avec la structure de
ListTile
, ses propriétés essentielles (title, subtitle, leading, trailing, etc.), et comment ces éléments peuvent être agencés pour afficher des informations structurées. - Apprendre à utiliser les fonctionnalités interactives intégrées, telles que l’ajout de cases à cocher (
CheckboxListTile
), de boutons radio (RadioListTile
), et d’interrupteurs (SwitchListTile
), afin de capter les choix et préférences des utilisateurs. - Etre capable de styliser le
ListTile
pour qu’il s’intègre à l’identité visuelle de l’application, en ajustant les icônes, les couleurs, les marges, et en ajoutant des éléments personnalisés. - Connaitre comment associer des actions (comme la navigation vers d’autres pages) aux éléments ListTile pour créer une expérience interactive et fluide, par exemple en utilisant onTap pour déclencher des interactions.
- Bien utiliser le
ListTile
dans des listes dynamiques et générées, comme celles affichant des éléments à partir de bases de données ou d’API, pour une application responsive et évolutive. -
Présentation
- Le widget ListTile est un composant très utile dans Flutter pour créer des listes d’éléments qui peuvent être sélectionnés, ou qui montrent simplement des informations. Il est souvent utilisé à l’intérieur de listes déroulantes comme ListView, GridView, ListWheelScrollView, etc. pour afficher des éléments dans une liste.
-
Composant du ListTile : Structuration d’Éléments dans une Liste
- Un ListTile typique est divisé en trois sections ; Début, Centre et Fin.
- Début (Leading) : Cette section contient généralement le widget principal, tel qu’une icône ou une image. C’est affiché à gauche du contenu principal du ListTile.
- Centre (Title et Subtitle) : Cette section comprend le titre principal et éventuellement un sous-titre. Le titre est généralement le texte principal que vous souhaitez afficher, tandis que le sous-titre peut fournir des informations supplémentaires.
- Fin (Trailing) : Cette section est située à droite du contenu principal du ListTile. Elle contient généralement un widget tel qu’une icône, un bouton ou tout autre élément d’action. Cela peut être utilisé pour indiquer une action supplémentaire associée à l’élément du ListTile.
- Voici un exemple illustrant ces trois sections dans un ListTile :
- Dans cet exemple :
leading
contient une icône qui est située à gauche du texte principal.title
contient le texte principal, « John Doe ».subtitle
contient le sous-titre, « john.doe@example.com ».trailing
contient une icône qui est située à droite du texte principal et du sous-titre.- Ces sections offrent une grande flexibilité pour la conception et l’affichage des éléments dans une liste dans Flutter.
-
Variantes du ListTile
- Le
widget ListTile
est incroyablement polyvalent, et ses variantes offrent encore plus de possibilités de personnalisation. Voici quelques-unes des variantes les plus couramment utilisées : -
ListTile simple
-
Exemple:
ListTile simple
: Cette variante est la version de base du ListTile. Elle comprend une icône ou une image à gauche, un titre au centre, et éventuellement une icône ou un bouton facultatif à droite.-
Exemple: Autre écriture
ListTile(
leading: Icon(Icons.person), // Début
title: Text('John Doe'), // Centre - Titre
subtitle: Text('john.doe@example.com'), // Centre - Sous-titre
trailing: Icon(Icons.arrow_forward), // Fin
onTap: () {
// Action à effectuer lorsque l'utilisateur appuie sur cet élément
print('ListTile tapped');
},
)
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('ListTile Simple Example'),
),
body: ListView(
children: [
ListTile(
leading: Icon(Icons.car_rental),
title: Text('Voiture'),
trailing: Icon(Icons.more_vert),
onTap: () {},
),
ListTile(
leading: Icon(Icons.flight),
title: Text('Avion'),
trailing: Icon(Icons.more_vert),
onTap: () {},
),
ListTile(
leading: Icon(Icons.train),
title: Text('Train'),
trailing: Icon(Icons.more_vert),
onTap: () {},
),
ListTile(
leading: Icon(Icons.directions_bus),
title: Text('Bus'),
trailing: Icon(Icons.more_vert),
onTap: () {},
),
ListTile(
leading: Icon(Icons.bike_scooter),
title: Text('Scooter'),
trailing: Icon(Icons.more_vert),
onTap: () {},
),
ListTile(
leading: Icon(Icons.directions_boat),
title: Text('Bateau'),
trailing: Icon(Icons.more_vert),
onTap: () {},
),
ListTile(
leading: Icon(Icons.local_shipping),
title: Text('Camion'),
trailing: Icon(Icons.more_vert),
onTap: () {},
),
ListTile(
leading: Icon(Icons.directions_walk),
title: Text('À pied'),
trailing: Icon(Icons.more_vert),
onTap: () {},
),
ListTile(
leading: Icon(Icons.directions_bike),
title: Text('Vélo'),
trailing: Icon(Icons.more_vert),
onTap: () {},
),
ListTile(
leading: Icon(Icons.motorcycle),
title: Text('Moto'),
trailing: Icon(Icons.more_vert),
onTap: () {},
),
ListTile(
leading: Icon(Icons.tram),
title: Text('Tramway'),
trailing: Icon(Icons.more_vert),
onTap: () {},
),
ListTile(
leading: Icon(Icons.subway),
title: Text('Métro'),
trailing: Icon(Icons.more_vert),
onTap: () {},
),
ListTile(
leading: Icon(Icons.directions_car),
title: Text('Covoiturage'),
trailing: Icon(Icons.more_vert),
onTap: () {},
),
],
),
),
);
}
}
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Liste des éléments avec icônes et titres en français
final items = [
{'icon': Icons.car_rental, 'title': 'Voiture'},
{'icon': Icons.flight, 'title': 'Avion'},
{'icon': Icons.train, 'title': 'Train'},
{'icon': Icons.directions_bus, 'title': 'Bus'},
{'icon': Icons.bike_scooter, 'title': 'Scooter'},
{'icon': Icons.directions_boat, 'title': 'Bateau'},
{'icon': Icons.local_shipping, 'title': 'Camion'},
{'icon': Icons.directions_walk, 'title': 'À pied'},
{'icon': Icons.directions_bike, 'title': 'Vélo'},
{'icon': Icons.motorcycle, 'title': 'Moto'},
{'icon': Icons.tram, 'title': 'Tramway'},
{'icon': Icons.subway, 'title': 'Métro'},
{'icon': Icons.directions_car, 'title': 'Covoiturage'},
];
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Exemple de ListTile Simple'),
),
body: ListView(
children: items
.map((item) => ListTile(
leading: Icon(item['icon'] as IconData),
title: Text(item['title'] as String),
trailing: Icon(Icons.more_vert),
onTap: () {},
))
.toList(),
),
),
);
}
}
ListTile avec interrupteur (Switch)
ListTile avec interrupteur (Switch)
: Cette variante ajoute un interrupteur à la fin du ListTile, ce qui permet à l’utilisateur de basculer facilement entre deux valeurs booléennes.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State {
bool _switchValue = false;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('ListTile avec Switch'),
),
body: ListView(
children: [
ListTile(
title: Text('Notification Push'),
trailing: Switch(
value: _switchValue,
onChanged: (newValue) {
setState(() {
_switchValue = newValue;
});
},
),
),
],
),
),
);
}
}
ListTile avec sous-titre
ListTile avec sous-titre
: En plus des composants du ListTile simple, cette variante inclut un sous-titre en dessous du titre. Cela peut être utile pour fournir plus de contexte ou d’informations sur l’élément affiché.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('ListTile avec Sous-titre'),
),
body: ListView(
children: [
ListTile(
leading: Icon(Icons.book),
title: Text('Article Flutter'),
subtitle: Text('Introduction à Flutter et Dart'),
trailing: Icon(Icons.arrow_forward),
onTap: () {
// Action à effectuer lorsque l'utilisateur appuie sur cet élément
print('ListTile tapped');
},
),
ListTile(
leading: Icon(Icons.book),
title: Text('Article Dart'),
subtitle: Text('Introduction au langage de programmation Dart'),
trailing: Icon(Icons.arrow_forward),
onTap: () {
// Action à effectuer lorsque l'utilisateur appuie sur cet élément
print('ListTile tapped');
},
),
],
),
),
);
}
}
ListTile avec icône uniquement
ListTile avec icône uniquement
: Cette variante ne comporte qu’une icône, sans texte. Elle est pratique pour afficher des symboles ou des logos plutôt que du texte.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('ListTile avec Icône uniquement'),
),
body: ListView(
children: [
ListTile(
leading: Icon(Icons.camera),
onTap: () {
// Action à effectuer lorsque l'utilisateur appuie sur cet élément
print('ListTile tapped');
},
),
ListTile(
leading: Icon(Icons.album),
onTap: () {
// Action à effectuer lorsque l'utilisateur appuie sur cet élément
print('ListTile tapped');
},
),
],
),
),
);
}
}
ListTile avec case à cocher
ListTile avec case à cocher
: Cette variante comprend une case à cocher à gauche, permettant aux utilisateurs de sélectionner plusieurs éléments ou de les marquer comme terminés. Le titre et un sous-titre facultatif peuvent être inclus à droite.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State {
bool _isChecked1 = false;
bool _isChecked2 = false;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('ListTile avec Case à cocher'),
),
body: ListView(
children: [
ListTile(
leading: Checkbox(
value: _isChecked1,
onChanged: (bool? value) {
setState(() {
_isChecked1 = value!;
});
},
),
title: Text('Tâche 1'),
subtitle: Text('Description de la tâche 1'),
onTap: () {
setState(() {
_isChecked1 = !_isChecked1;
});
},
),
ListTile(
leading: Checkbox(
value: _isChecked2,
onChanged: (bool? value) {
setState(() {
_isChecked2 = value!;
});
},
),
title: Text('Tâche 2'),
subtitle: Text('Description de la tâche 2'),
onTap: () {
setState(() {
_isChecked2 = !_isChecked2;
});
},
),
],
),
),
);
}
}
ListTile avec bouton radio
ListTile avec bouton radio
: Similaire à la variante avec case à cocher, mais avec des boutons radio à la place. Seul un élément peut être sélectionné à la fois, ce qui en fait un choix idéal pour les options ou les choix exclusifs.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State {
int _selectedValue = 0;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('ListTile avec Bouton Radio'),
),
body: ListView(
children: [
ListTile(
leading: Radio(
value: 1,
groupValue: _selectedValue,
onChanged: (value) {
setState(() {
_selectedValue = value as int;
});
},
),
title: Text('Option 1'),
onTap: () {
setState(() {
_selectedValue = 1;
});
},
),
ListTile(
leading: Radio(
value: 2,
groupValue: _selectedValue,
onChanged: (value) {
setState(() {
_selectedValue = value as int;
});
},
),
title: Text('Option 2'),
onTap: () {
setState(() {
_selectedValue = 2;
});
},
),
],
),
),
);
}
}
ListTile personnalisé
ListTile personnalisé
: Cette variante offre une flexibilité maximale en permettant aux utilisateurs d’ajouter leurs propres widgets ou éléments au ListTile. Cela peut inclure des images, des boutons, ou du texte supplémentaire, offrant ainsi une personnalisation totale de l’apparence et du comportement du ListTile.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('ListTile Personnalisé'),
),
body: ListView(
children: [
CustomListTile(
title: 'Mon Titre',
subtitle: 'Mon sous-titre',
leading: Icon(Icons.person),
trailing: Icon(Icons.arrow_forward),
onTap: () {
// Action à effectuer lorsque l'utilisateur appuie sur cet élément
print('ListTile personnalisé tapé');
},
),
],
),
),
);
}
}
class CustomListTile extends StatelessWidget {
final String title;
final String subtitle;
final Widget leading;
final Widget trailing;
final VoidCallback onTap;
const CustomListTile({
required this.title,
required this.subtitle,
required this.leading,
required this.trailing,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return ListTile(
leading: leading,
title: Text(title),
subtitle: Text(subtitle),
trailing: trailing,
onTap: onTap,
);
}
}
Application
-
Partie:01
- Reprenez le code donné pour le widget « ListTile simple ».
- Ajoutez une couleur d’arrière-plan au « AppBar » et le texte « Utiliser ListTile ».
- Supprimez la barre oblique située à droite de l’écran.
- Centrez les deux ListTile au centre haut de l’écran et ajoutez un espace autour des ListTiles.
- Colorez les ListTiles et ajoutez les numéros de téléphone sous chaque nom.
- Coloriez chaque ListTile avec une couleur différente.
-
Partie:02
- Comment pourriez-vous modifier ce code pour remplacer les ListTile par des ListTile avec interrupteur (Switch) tout en conservant le même agencement et la même disposition centrée ?
- En utilisant l’exemple donné, expliquez comment vous pourriez adapter la gestion des événements (onTap) pour chaque ListTile si vous deviez utiliser un interrupteur (Switch) à la place.
-
Partie:03
-
Partie:04
- En utilisant l’exemple donné de ListTile avec interrupteur (Switch), pouvez-vous ajouter deux autres ListTile à la liste existante ? Cette fois-ci, les nouveaux ListTile devraient contenir une case à cocher à gauche, permettant aux utilisateurs de sélectionner plusieurs éléments ou de les marquer comme terminés.
-
« Imaginez que vous ayez ajouté des interrupteurs (Switch) à chaque ListTile de votre application. Cependant, lorsque vous essayez de changer l’état des interrupteurs, ceux-ci ne restent pas dans leur place et leur valeur ne se met pas à jour. Pouvez-vous identifier la raison pour laquelle cela se produit? Si non, proposez une solution pour corriger ce problème. »