Créer un design responsive avec MediaQuery
Sommaire
- 1- Objectif
- 2- Présentation
- 3- La classe
MediaQuery
en Flutter - 3.1- Exemples d'utilisation de MediaQuery
- 3.2- Exemples d'utilisation de MediaQuery
- 3.3- Exemple:01
- 3.4- Exemple:02
- 4- Exercices d'application
- 4.1- Exercice 1 : Interface réactive de page d'accueil
- 4.2- Exercice 2 : Application de gestion de tâches réactive
- 4.2.1- Cours Flutter
Créer un design responsive avec MediaQuery dans Flutter
-
Objectif
- Être capable d’utiliser la fonction
MediaQuery.of(context)
dans Flutter. -
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.
- 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.-
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.
- 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é.
-
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 :
- 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 :
- 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 :
- 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 :
-
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. -
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 :
-
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.
- 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 :
- Créez une nouvelle classe HomePage en ajoutant le code suivant au-dessus de la classe MyApp :
- Créez deux classes
ArticlesColumn
etAdsColumn
pour afficher les articles et les publicités. - Voici un exemple de code pour la classe
ArticlesColumn
, faites de même pourAdsColumn
: - 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.
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é.
final Orientation orientation = MediaQuery.of(context).orientation;
final Size size = MediaQuery.of(context).size;
Code
double fontSize = MediaQuery.of(context).size.width > 600 ? 24.0 : 16.0;
Text(
'Texte adaptable',
style: TextStyle(fontSize: fontSize),
);
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
}
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
}
Code
double margin = MediaQuery.of(context).size.width > 600 ? 16.0 : 8.0;
Container(
margin: EdgeInsets.all(margin),
child: ...,
);
Résultat souhaité
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
),
);
}
}
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(),
],
);
}
}
Solution
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(),
);
}
}
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]),
);
},
);
}
}
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]),
);
},
);
}
}
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}'),
],
),
),
);
}
}
}