Widgets d'input spécialisés Flutter - Switch, Checkbox, Radio, Slider, Dropdown
Introduction aux widgets d’input
Section titled “Introduction aux widgets d’input”Flutter propose une gamme complète de widgets d’input spécialisés pour différents types de saisie : boutons à bascule, cases à cocher, boutons radio, curseurs et listes déroulantes.
Switch
Section titled “Switch”Le Switch permet de créer un interrupteur binaire :
class SwitchExample extends StatefulWidget { @override _SwitchExampleState createState() => _SwitchExampleState();}
class _SwitchExampleState extends State<SwitchExample> { bool switched = false;
@override Widget build(BuildContext context) { return Switch( value: switched, onChanged: (value) => setState(() => switched = value), ); }}Checkbox
Section titled “Checkbox”class CheckboxExample extends StatefulWidget { @override _CheckboxExampleState createState() => _CheckboxExampleState();}
class _CheckboxExampleState extends State<CheckboxExample> { bool checked = false;
@override Widget build(BuildContext context) { return Row( children: [ Checkbox( value: checked, onChanged: (value) => setState(() => checked = value!), ), InkWell( child: const Text("J'accepte les CGU !"), onTap: () => setState(() => checked = !checked), ), ], ); }}Radio buttons
Section titled “Radio buttons”Les boutons radio permettent de sélectionner une option parmi plusieurs :
class RadioExample extends StatefulWidget { @override _RadioExampleState createState() => _RadioExampleState();}
class _RadioExampleState extends State<RadioExample> { int radioSelection = 1;
@override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Row( children: [ Radio<int>( value: 1, groupValue: radioSelection, onChanged: (value) => setState(() => radioSelection = value!), ), const Text('Option 1') ], ), Row( children: [ Radio<int>( value: 2, groupValue: radioSelection, onChanged: (value) => setState(() => radioSelection = value!), ), const Text('Option 2') ], ), ], ); }}Slider
Section titled “Slider”Le Slider permet la sélection d’une valeur numérique :
class SliderExample extends StatefulWidget { @override _SliderExampleState createState() => _SliderExampleState();}
class _SliderExampleState extends State<SliderExample> { double sliderValue = 5.0;
@override Widget build(BuildContext context) { return Column( children: [ Text('Valeur: ${sliderValue.toStringAsFixed(1)}'), Slider( value: sliderValue, min: 0, max: 10, divisions: 100, label: '${sliderValue.toStringAsPrecision(3)}', onChanged: (value) => setState(() => sliderValue = value), ), ], ); }}DropdownButton
Section titled “DropdownButton”class DropdownExample extends StatefulWidget { @override _DropdownExampleState createState() => _DropdownExampleState();}
class _DropdownExampleState extends State<DropdownExample> { int? citySelection;
@override Widget build(BuildContext context) { return DropdownButton<int>( value: citySelection, hint: const Text('Sélectionnez votre destination'), items: const [ DropdownMenuItem(child: Text('Madrid'), value: 1), DropdownMenuItem(child: Text('Rome'), value: 2), DropdownMenuItem(child: Text('Lisbonne'), value: 3), ], onChanged: (int? value) => setState(() => citySelection = value), ); }}AutoComplete
Section titled “AutoComplete”Le widget Autocomplete intègre un mécanisme de suggestion automatique :
const cities = ['Paris', 'Lyon', 'Marseille', 'Toulouse', 'Nice'];
class AutoCompleteExample extends StatefulWidget { @override _AutoCompleteExampleState createState() => _AutoCompleteExampleState();}
class _AutoCompleteExampleState extends State<AutoCompleteExample> { String? selectedCity;
@override Widget build(BuildContext context) { return Column( children: [ Autocomplete<String>( optionsBuilder: (TextEditingValue value) { if (value.text.isEmpty) return <String>[]; return cities.where((element) => element.toLowerCase().contains(value.text.toLowerCase()) ); }, onSelected: (value) => setState(() => selectedCity = value), fieldViewBuilder: (context, controller, focusNode, onEditingComplete) { return TextFormField( controller: controller, focusNode: focusNode, onEditingComplete: onEditingComplete, decoration: InputDecoration( labelText: 'Ville', border: OutlineInputBorder(), ), ); }, ), if (selectedCity != null) Padding( padding: const EdgeInsets.all(8.0), child: Text('Ville sélectionnée: $selectedCity'), ), ], ); }}Exemple complet avec plusieurs widgets
Section titled “Exemple complet avec plusieurs widgets”Voici un exemple intégrant plusieurs widgets d’input :
class CompleteInputForm extends StatefulWidget { @override _CompleteInputFormState createState() => _CompleteInputFormState();}
class _CompleteInputFormState extends State<CompleteInputForm> { bool _notifications = true; bool _acceptTerms = false; int _priority = 1; double _budget = 50.0; String? _category;
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Formulaire complet')), body: Padding( padding: EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Switch Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Notifications'), Switch( value: _notifications, onChanged: (value) => setState(() => _notifications = value), ), ], ),
// Checkbox Row( children: [ Checkbox( value: _acceptTerms, onChanged: (value) => setState(() => _acceptTerms = value!), ), Text('J\'accepte les conditions d\'utilisation'), ], ),
// Radio buttons Text('Priorité:'), Row( children: [ Radio<int>( value: 1, groupValue: _priority, onChanged: (value) => setState(() => _priority = value!), ), Text('Normale'), Radio<int>( value: 2, groupValue: _priority, onChanged: (value) => setState(() => _priority = value!), ), Text('Élevée'), ], ),
// Slider Text('Budget: ${_budget.toStringAsFixed(0)}€'), Slider( value: _budget, min: 0, max: 100, divisions: 10, onChanged: (value) => setState(() => _budget = value), ),
// Dropdown DropdownButton<String>( value: _category, hint: Text('Sélectionner une catégorie'), isExpanded: true, items: [ DropdownMenuItem(child: Text('Personnel'), value: 'personal'), DropdownMenuItem(child: Text('Professionnel'), value: 'work'), DropdownMenuItem(child: Text('Urgent'), value: 'urgent'), ], onChanged: (value) => setState(() => _category = value), ),
SizedBox(height: 20),
ElevatedButton( onPressed: _acceptTerms ? () { // Traitement du formulaire print('Notifications: $_notifications'); print('Priorité: $_priority'); print('Budget: $_budget'); print('Catégorie: $_category'); } : null, child: Text('Valider'), ), ], ), ), ); }}Bonnes pratiques pour les widgets d’input
Section titled “Bonnes pratiques pour les widgets d’input”1. Groupement logique
Section titled “1. Groupement logique”Groupez les widgets similaires dans des sections distinctes :
Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Préférences', style: Theme.of(context).textTheme.headline6), SwitchListTile( title: Text('Notifications push'), subtitle: Text('Recevoir des notifications'), value: _pushNotifications, onChanged: (value) => setState(() => _pushNotifications = value), ), SwitchListTile( title: Text('Mode sombre'), subtitle: Text('Interface sombre'), value: _darkMode, onChanged: (value) => setState(() => _darkMode = value), ), ],)2. Validation des widgets personnalisés
Section titled “2. Validation des widgets personnalisés”Assurez-vous que les valeurs obligatoires sont sélectionnées :
String? _validateSelection() { if (_category == null) { return 'Veuillez sélectionner une catégorie'; } if (!_acceptTerms) { return 'Vous devez accepter les conditions'; } return null;}3. Accessibilité
Section titled “3. Accessibilité”Ajoutez des labels appropriés pour l’accessibilité :
Semantics( label: 'Activer les notifications', child: Switch( value: _notifications, onChanged: (value) => setState(() => _notifications = value), ),)