Avez-vous une question? (216) 97 656 803 hajjriadh@gmail.com
Flutter

Créer un design responsive avec MediaQuery

Un cours complet pour maîtriser Créer un design responsive avec MediaQuery.

0 chapitres 0 QCM Accès gratuit
  1. Objectif

    • Être capable d'utiliser la fonction MediaQuery.of(context) dans Flutter.
  2. Présentation

    • Une application responsive est une application écrite de manière à s'adapter à la taille d'écran disponible de l'appareil sur lequel elle est affichée. Ceci est souvent réalisé par l'application qui restitue l'interface utilisateur si l'utilisateur redimensionne l'écran ou si l'orientation de l'appareil est modifiée.
    • Au cours du processus de développement d'une application pour les téléphones et les tablettes, il est de pratique courante d'avoir différentes dispositions d'interface utilisateur pour différentes tailles d'écran pour une meilleure expérience utilisateur.
    • La conception responsive, ou responsive design, est une approche de conception d'interfaces utilisateur qui vise à rendre les applications et les sites web flexibles pour différents types et tailles d'écrans. Cette flexibilité est essentielle pour offrir une expérience utilisateur optimale, quel que soit l'appareil utilisé.
    • Flutter, avec ses widgets et son architecture, fournit plusieurs outils pour rendre cette conception responsive plus facile.
      • La classe MediaQuery en Flutter
      • LayoutBuilder: Donne les contraintes parentes pour aider à prendre des décisions sur la disposition.
      • FractionallySizedBox: Un widget qui taille son enfant à une fraction de l'espace total disponible.
      • AspectRatio: Force l'enfant à avoir un ratio d'aspect spécifique.
  3. La classe MediaQuery en Flutter

    • Comme son nom l'indique, le widget MediaQuery contient des informations sur un média. Vous l'avez bien deviné, ici média signifie fenêtre, avec sa taille ou son orientation .
    • La classe MediaQuery sera utile lorsqu'elle est utilisée avec le contexte de l'application en cours d'exécution.
    • MediaQuery est un widget qui peut être utilisé pour obtenir la taille, l'orientation et d'autres propriétés de l'écran actuel. Il est extrêmement utile pour prendre des décisions sur la façon de disposer ou de styliser les widgets en fonction des caractéristiques de l'écran.
    • Vous pouvez utiliser pour récupérer la taille (largeur/hauteur) et l'orientation (portrait/paysage) de l'écran.
    • Grâce à MediaQuery, vous pouvez obtenir des informations sur la taille de l'appareil sur lequel vous vous trouvez, ainsi que sur les préférences de l'utilisateur, et créer votre mise en page en conséquence.
    • MediaQuery fournit une vue de niveau supérieur de la taille de l'écran de votre application et peut fournir des informations plus détaillées sur les préférences de mise en page de l'utilisateur.
    • Il existe deux modes principaux dans Flutter. Ils sont en mode portrait et en mode paysage. Du coup, quand on change de mode, le look change aussi.
    • MediaQuery fournit une vue de niveau supérieur de la taille de l’écran de l’application actuelle et peut également fournir des informations plus détaillées sur l’appareil et ses préférences de mise en page.
    • Le widget MediaQuery est le premier endroit où vous devriez regarder si vous essayez d'obtenir des informations spécifiques sur l'appareil physique sur lequel votre application s'exécute, ou si vous souhaitez manipuler l'appareil. Vous pouvez l'utiliser pour :
      • Demandez si le téléphone est actuellement en orientation portrait ou paysage.
           final Orientation orientation = MediaQuery.of(context).orientation;
      • Désactivez les animations et inversez les couleurs pour des raisons d'accessibilité.
      • Demandez au téléphone si l'utilisateur voit son facteur de taille de texte augmenté.
           final Size size = MediaQuery.of(context).size;
      • Exemples d'utilisation de MediaQuery
        • Ajuster la taille de la police en fonction de la taille de l'écran :
          • Vous pouvez augmenter ou diminuer la taille de la police en fonction de la taille de l'écran. Par exemple, vous pouvez rendre la police plus grande sur les tablettes et plus petite sur les téléphones :
          • Code
               double fontSize = MediaQuery.of(context).size.width > 600 ? 24.0 : 16.0;
              
              Text(
                'Texte adaptable',
                style: TextStyle(fontSize: fontSize),
              );
        • Afficher ou masquer des éléments en fonction de la taille de l'écran :
          • Vous pouvez décider d'afficher ou de masquer certains widgets en fonction de la largeur de l'écran. Par exemple, vous pouvez masquer une barre latérale de navigation sur les petits écrans :
          • Code
               bool showSidebar = MediaQuery.of(context).size.width > 800;
              
              if (showSidebar) {
                // Afficher la barre latérale de navigation
              } else {
                // Ne pas afficher la barre latérale de navigation
              }
        • Modifier la disposition en fonction de l'orientation de l'écran :
          • Vous pouvez également utiliser MediaQuery pour détecter l'orientation de l'écran (portrait ou paysage) et ajuster votre disposition en conséquence :
          • Code
               final orientation = MediaQuery.of(context).orientation;
              
              if (orientation == Orientation.portrait) {
                // Afficher une disposition adaptée au mode portrait
              } else {
                // Afficher une disposition adaptée au mode paysage
              }
        • Adapter les marges et les espacements :
          • Vous pouvez ajuster les marges et les espacements en fonction de la taille de l'écran pour une meilleure apparence visuelle. Par exemple, augmentez les marges sur les grands écrans pour mieux utiliser l'espace disponible :
          • Code
               double margin = MediaQuery.of(context).size.width > 600 ? 16.0 : 8.0;
              
              Container(
                margin: EdgeInsets.all(margin),
                child: ...,
              );
      • Exemples d'utilisation de MediaQuery
        • Exemple:01
          • L’utilisation de mediaQuery.of entraîne automatiquement la reconstruction des widgets en fonction de la taille actuelle des appareils et des préférences de mise en page à chaque fois qu’ils changent.
          • Résultat souhaité

            Créer un design responsive  avec MediaQuery dans Flutter

            Solution
               import 'package:flutter/material.dart';
              void main() {
                runApp(const MyApp());
              }
              class MyApp extends StatelessWidget {
                const MyApp({Key? key}) : super(key: key);
                @override
                Widget build(BuildContext context) {
                  return MaterialApp(
                    title: 'Flutter Demo',
                    theme: ThemeData(
                      primarySwatch: Colors.blue,
                    ),
                    home: Home(title: 'Flutter Demo Home Page'),
                    debugShowCheckedModeBanner: false, //supprimer la bannière de debug
                  );
                }
              }
              class Home extends StatelessWidget {
                var size, height, width;
                Home({Key? key, required String title}) : super(key: key);
                @override
                Widget build(BuildContext context) {// obtenir la taille de la fenêtre
                  size = MediaQuery.of(context).size;
                  height = size.height;
                  width = size.width;
                  return Scaffold(
                    appBar: AppBar(
                      title: const Text("Tutoriel MediaQuery"),
                      backgroundColor: Colors.blueGrey,
                    ),
                    body: Container(
                      color: Colors.cyan,
                      height: height / 2, //La moitié de la taille de la hauteur
                      width: width / 2, //La moitié de la taille de la largeur
                    ),
                  );
                }
              }
        • Exemple:02
          • Supposons que vous souhaitiez avoir une disposition de colonne sur les écrans étroits (comme les téléphones) et une disposition de ligne sur les écrans larges (comme les tablettes). Vous pourriez le faire comme ceci :
          • Solution
               Widget build(BuildContext context) {
                double width = MediaQuery.of(context).size.width;
              
                if (width > 600) {
                  // Retourner une disposition de ligne pour les écrans larges
                  return Row(
                    children: [
                      WidgetEnfant1(),
                      WidgetEnfant2(),
                    ],
                  );
                } else {
                  // Retourner une disposition de colonne pour les écrans étroits
                  return Column(
                    children: [
                      WidgetEnfant1(),
                      WidgetEnfant2(),
                    ],
                  );
                }
              }
      • Exercices d'application

        • Exercice 1 : Interface réactive de page d'accueil
          • Objectif : Créez une page d'accueil réactive avec deux colonnes, une pour les articles et l'autre pour les publicités. La disposition doit s'adapter en fonction de la largeur de l'écran.
            • Créez une application Flutter avec une page d'accueil vide.
            • Utilisez MediaQuery pour détecter la largeur de l'écran.
            • Si la largeur de l'écran est supérieure à 600 pixels, affichez les articles et les publicités dans deux colonnes côte à côte. Sinon, affichez-les en une seule colonne l'un en dessous de l'autre.
            • Créez une liste d'exemples d'articles et une liste d'exemples de publicités.
            • Affichez les articles et les publicités en utilisant des ListView dans les colonnes correspondantes.
            • Assurez-vous que l'interface utilisateur s'adapte de manière transparente lorsque vous redimensionnez l'écran.
            Solution
            • Créez un nouveau projet Flutter en utilisant la commande flutter create nom_de_votre_projet dans votre terminal.
            • Ouvrez le fichier lib/main.dart de votre projet.
            • Importez les packages nécessaires en ajoutant les lignes suivantes en haut du fichier :
                import 'package:flutter/material.dart';
                //Remplacez la classe MyApp par la suivante :
                void main() {
                  runApp(MyApp());
                }
                
                class MyApp extends StatelessWidget {
                  @override
                  Widget build(BuildContext context) {
                    return MaterialApp(
                      home: HomePage(),
                    );
                  }
                }
            • Créez une nouvelle classe HomePage en ajoutant le code suivant au-dessus de la classe MyApp :
                class HomePage extends StatelessWidget {
                  @override
                  Widget build(BuildContext context) {
                    final screenWidth = MediaQuery.of(context).size.width;
                
                    if (screenWidth > 600) {
                      return Scaffold(
                        appBar: AppBar(
                          title: Text('Page d\'accueil'),
                        ),
                        body: Row(
                          children: [
                            Expanded(
                              child: ArticlesColumn(),
                            ),
                            Expanded(
                              child: AdsColumn(),
                            ),
                          ],
                        ),
                      );
                    } else {
                      return Scaffold(
                        appBar: AppBar(
                          title: Text('Page d\'accueil'),
                        ),
                        body: Column(
                          children: [
                            Flexible(
                              child: ArticlesColumn(),
                            ),
                            Flexible(
                              child: AdsColumn(),
                            ),
                          ],
                        ),
                      );
                    }
                  }
                }
                
                class ArticlesColumn extends StatelessWidget {
                  @override
                  Widget build(BuildContext context) {
                    final articles = [
                      'Article 1',
                      'Article 2',
                      'Article 3',
                    ];
                
                    return ListView.builder(
                      itemCount: articles.length,
                      itemBuilder: (context, index) {
                        return ListTile(
                          title: Text(articles[index]),
                        );
                      },
                    );
                  }
                }
                
                class AdsColumn extends StatelessWidget {
                  @override
                  Widget build(BuildContext context) {
                    final ads = [
                      'Publicité 1',
                      'Publicité 2',
                      'Publicité 3',
                    ];
                
                    return ListView.builder(
                      itemCount: ads.length,
                      itemBuilder: (context, index) {
                        return ListTile(
                          title: Text(ads[index]),
                        );
                      },
                    );
                  }
                }
            • Créez deux classes ArticlesColumn et AdsColumn pour afficher les articles et les publicités.
            • Voici un exemple de code pour la classe ArticlesColumn, faites de même pour AdsColumn:
                class ArticlesColumn extends StatelessWidget {
                  @override
                  Widget build(BuildContext context) {
                    // Créez une liste d'exemples d'articles
                    final articles = [
                      'Article 1',
                      'Article 2',
                      'Article 3',
                    ];
                
                    return ListView.builder(
                      itemCount: articles.length,
                      itemBuilder: (context, index) {
                        return ListTile(
                          title: Text(articles[index]),
                        );
                      },
                    );
                  }
                }
            • Pour la classe AdsColumn, créez une liste d'exemples de publicités de la même manière que les articles.
            • Assurez-vous d'ajouter les widgets ArticlesColumn et AdsColumn à la classe HomePage.
            • Exécutez votre application en utilisant la commande flutter run dans votre terminal.
        • Exercice 2 : Application de gestion de tâches réactive
          • Objectif : Créez une application de gestion de tâches réactive qui ajuste la disposition en fonction de la taille de l'écran.
            • Créez une application Flutter avec une liste de tâches vide.
            • Utilisez MediaQuery pour détecter la largeur de l'écran.
            • Si la largeur de l'écran est supérieure à 600 pixels, affichez la liste des tâches à gauche et les détails de la tâche sélectionnée à droite. Sinon, affichez la liste des tâches en haut et les détails de la tâche sélectionnée en dessous.
            • Créez une classe Task pour représenter une tâche avec des propriétés telles que le nom, la date d'échéance, la priorité, etc.
            • Créez une liste d'exemples de tâches.
            • Affichez la liste des tâches et les détails de la tâche sélectionnée en utilisant des widgets appropriés.
            • Assurez-vous que l'interface utilisateur s'adapte de manière transparente lorsque vous redimensionnez l'écran.
          Solution
            import 'package:flutter/material.dart';
            
            void main() {
              runApp(MyApp());
            }
            
            class Task {
              final String name;
              final String dueDate;
              final String priority;
            
              Task({
                required this.name,
                required this.dueDate,
                required this.priority,
              });
            }
            
            class MyApp extends StatelessWidget {
              @override
              Widget build(BuildContext context) {
                return MaterialApp(
                  home: HomePage(),
                );
              }
            }
            
            class HomePage extends StatefulWidget {
              @override
              _HomePageState createState() => _HomePageState();
            }
            
            class _HomePageState extends State {
              final List tasks = [
                Task(name: 'Tâche 1', dueDate: '2023-09-30', priority: 'Élevée'),
                Task(name: 'Tâche 2', dueDate: '2023-10-15', priority: 'Moyenne'),
                Task(name: 'Tâche 3', dueDate: '2023-10-01', priority: 'Basse'),
              ];
            
              Task? selectedTask;
            
              @override
              Widget build(BuildContext context) {
                final screenWidth = MediaQuery.of(context).size.width;
            
                if (screenWidth > 600) {
                  return Scaffold(
                    appBar: AppBar(
                      title: Text('Liste de tâches'),
                    ),
                    body: Row(
                      children: [
                        Flexible(
                          flex: 2,
                          child: TaskList(tasks: tasks, onTaskSelected: (task) {
                            setState(() {
                              selectedTask = task;
                            });
                          }),
                        ),
                        Flexible(
                          flex: 3,
                          child: TaskDetails(task: selectedTask),
                        ),
                      ],
                    ),
                  );
                } else {
                  return Scaffold(
                    appBar: AppBar(
                      title: Text('Liste de tâches'),
                    ),
                    body: Column(
                      children: [
                        TaskList(tasks: tasks, onTaskSelected: (task) {
                          setState(() {
                            selectedTask = task;
                          });
                        }),
                        TaskDetails(task: selectedTask),
                      ],
                    ),
                  );
                }
              }
            }
            
            class TaskList extends StatelessWidget {
              final List tasks;
              final Function(Task)? onTaskSelected;
            
              TaskList({required this.tasks, this.onTaskSelected});
            
              @override
              Widget build(BuildContext context) {
                return ListView.builder(
                  itemCount: tasks.length,
                  itemBuilder: (context, index) {
                    final task = tasks[index];
                    return ListTile(
                      title: Text(task.name),
                      subtitle: Text('Date d\'échéance : ${task.dueDate}\nPriorité : ${task.priority}'),
                      onTap: () {
                        if (onTaskSelected != null) {
                          onTaskSelected!(task);
                        }
                      },
                    );
                  },
                );
              }
            }
            
            class TaskDetails extends StatelessWidget {
              final Task? task;
            
              TaskDetails({required this.task});
            
              @override
              Widget build(BuildContext context) {
                if (task == null) {
                  return Expanded(
                    child: Container(
                      padding: EdgeInsets.all(16),
                      child: Text('Sélectionnez une tâche pour afficher les détails.'),
                    ),
                  );
                } else {
                  return Expanded(
                    child: Container(
                      padding: EdgeInsets.all(16),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text('Détails de la tâche :', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
                          SizedBox(height: 8),
                          Text('Nom : ${task!.name}'),
                          Text('Date d\'échéance : ${task!.dueDate}'),
                          Text('Priorité : ${task!.priority}'),
                        ],
                      ),
                    ),
                  );
                }
              }
            }