Prévisualisation des widgets Flutter
Sommaire
Directives de prévisualisation
Utilisez le Widget Previewer de Flutter pour afficher les widgets en temps réel, isolés du contexte complet de l'application.
- Éléments cibles : Appliquez l'annotation
@Previewà des fonctions de niveau supérieur, des méthodes statiques au sein d'une classe, ou des constructeurs/factories de widget publics sans arguments requis et retournant unWidgetouWidgetBuilder. - Imports : Importez toujours
package:flutter/widget_previews.dartpour accéder aux annotations de prévisualisation. - Annotations personnalisées : Étendez la classe
Previewpour créer des annotations personnalisées qui injectent des propriétés communes (par exemple, thèmes, wrappers) à travers plusieurs widgets. - Configurations multiples : Appliquez plusieurs annotations
@Previewà une même cible pour générer plusieurs instances de prévisualisation. Alternativement, étendezMultiPreviewpour encapsuler les configurations multi-prévisualisation courantes. - Transformations à l'exécution : Surchargez la méthode
transform()dans les classesPreviewouMultiPreviewpersonnalisées pour modifier les configurations de prévisualisation dynamiquement à l'exécution (par exemple, générer des noms basés sur des valeurs dynamiques, ce qui est impossible dans un contexteconst).
Gestion des limitations
Respectez les contraintes suivantes lors de la création de widgets prévisualisables, car le Widget Previewer s'exécute dans un environnement web :
- Pas d'APIs natives : N'utilisez pas de plugins natifs ni d'APIs provenant de
dart:iooudart:ffi. Les widgets avec des dépendances transitives surdart:iooudart:ffilèveront des exceptions lors de l'invocation. Utilisez des imports conditionnels pour les simuler ou les contourner en mode prévisualisation. - Chemins des ressources : Utilisez des chemins basés sur les packages pour les ressources chargées via les APIs
fromAssetdedart:ui(par exemple,packages/my_package_name/assets/my_image.pngau lieu deassets/my_image.png). - Callbacks publics : Assurez-vous que tous les arguments de callback fournis aux annotations de prévisualisation sont publics et constants pour satisfaire les exigences de génération de code.
- Contraintes : Appliquez des contraintes explicites via le paramètre
sizede l'annotation@Previewsi votre widget n'est pas contraint, car le previewer les contraint par défaut à approximativement la moitié de la fenêtre d'affichage.
Workflows
Créer une prévisualisation de widget
Copiez et suivez cette liste de contrôle lors de l'implémentation d'une nouvelle prévisualisation de widget :
- [ ] Importez
package:flutter/widget_previews.dart. - [ ] Identifiez une cible valide (fonction de niveau supérieur, méthode statique, ou constructeur public sans paramètres).
- [ ] Appliquez l'annotation
@Previewà la cible. - [ ] Configurez les paramètres de prévisualisation (
name,group,size,theme,brightness, etc.) selon vos besoins. - [ ] Si vous appliquez la même configuration à plusieurs widgets, extrayez la configuration dans une classe personnalisée étendant
Preview.
Interagir avec les prévisualisations
Suivez le workflow conditionnel approprié pour lancer et interagir avec le Widget Previewer :
Si vous utilisez un IDE supporté (Android Studio, IntelliJ, VS Code avec Flutter 3.38+) :
- Lancez l'IDE. Le Widget Previewer démarre automatiquement.
- Ouvrez l'onglet « Flutter Widget Preview » dans la barre latérale.
- Basculez « Filter previews by selected file » en bas à gauche si vous souhaitez afficher les prévisualisations en dehors du fichier actuellement actif.
Si vous utilisez la ligne de commande :
- Accédez au répertoire racine du projet Flutter.
- Exécutez
flutter widget-preview start. - Consultez l'environnement Chrome qui s'ouvre automatiquement.
Boucle de rétroaction : Itération de prévisualisation
- Modifiez le code du widget ou la configuration de prévisualisation.
- Observez la mise à jour automatique dans le Widget Previewer.
- Si l'état global (par exemple, les initialisateurs statiques) a été modifié : Cliquez sur le bouton de redémarrage à chaud global en bas à droite.
- Si seul l'état local du widget doit être réinitialisé : Cliquez sur le bouton de redémarrage à chaud individuel sur la carte de prévisualisation spécifique.
- Examinez les erreurs dans la console IDE/CLI -> corrigez -> répétez.
Exemples
Prévisualisation basique
import 'package:flutter/widget_previews.dart';
import 'package:flutter/material.dart';
@Preview(name: 'My Sample Text', group: 'Typography')
Widget mySampleText() {
return const Text('Hello, World!');
}
Prévisualisation personnalisée avec transformation à l'exécution
import 'package:flutter/widget_previews.dart';
import 'package:flutter/material.dart';
final class TransformativePreview extends Preview {
const TransformativePreview({
super.name,
super.group,
});
PreviewThemeData _themeBuilder() {
return PreviewThemeData(
materialLight: ThemeData.light(),
materialDark: ThemeData.dark(),
);
}
@override
Preview transform() {
final originalPreview = super.transform();
final builder = originalPreview.toBuilder();
builder
..name = 'Transformed - ${originalPreview.name}'
..theme = _themeBuilder;
return builder.toPreview();
}
}
@TransformativePreview(name: 'Custom Themed Button')
Widget myButton() => const ElevatedButton(onPressed: null, child: Text('Click'));
Implémentation MultiPreview
import 'package:flutter/widget_previews.dart';
import 'package:flutter/material.dart';
/// Crée automatiquement des prévisualisations en mode clair et sombre.
final class MultiBrightnessPreview extends MultiPreview {
const MultiBrightnessPreview({required this.name});
final String name;
@override
List<Preview> get previews => const [
Preview(brightness: Brightness.light),
Preview(brightness: Brightness.dark),
];
@override
List<Preview> transform() {
final previews = super.transform();
return previews.map((preview) {
final builder = preview.toBuilder()
..group = 'Brightness'
..name = '$name - ${preview.brightness!.name}';
return builder.toPreview();
}).toList();
}
}
@MultiBrightnessPreview(name: 'Primary Card')
Widget cardPreview() => const Card(child: Padding(padding: EdgeInsets.all(8.0), child: Text('Content')));