Guide Flutter: Développement d'Applications Mobiles Multiplateformes
Guide Flutter: Développement d'Applications Mobiles Multiplateformes
Platforms
ELAACHAK LOTFI
2023/2024
Sommaire
Introduction
Architecture de Flutter
Premier Application
Le langage Dart
Flutter et Sqlite
En général, la création d'une application mobile est une tâche très complexe et difficile. Il existe de
nombreux frameworks disponibles, qui fournissent d'excellentes fonctionnalités pour développer
des applications mobiles. Pour le développement d'applications mobiles, Android fournit un cadre
natif basé sur le langage Java et Kotlin, tandis qu'iOS fournit un cadre basé sur le langage
Objective-C / Swift. Ainsi, nous avons besoin de deux langages et frameworks différents pour
développer des applications pour les deux OS. Aujourd'hui, pour surmonter cette complexité,
plusieurs frameworks ont été introduits qui prennent en charge à la fois les systèmes d'exploitation
et les applications de bureau. Ces types de framework sont connus sous le nom d'outils de
développement multiplateformes « cross plateformes ».
Le cadre de développement multiplateforme a la capacité d'écrire un code et peut se déployer sur les
différentes plates-formes (Android, iOS et Desktop). Cela permet aux développeurs de gagner
beaucoup de temps et d'économiser des efforts de développement.
Flutter est une boîte à outils d'interface utilisateur pour créer des applications rapides, belles et
compilées en natif pour mobile, Web et bureau avec un langage de programmation et une base de
code unique. Il est gratuit et open-source. Il a été initialement développé à partir de Google et est
désormais géré selon une norme ECMA. Les applications Flutter utilisent le langage de
programmation Dart pour créer une application. La programmation de fléchettes partage plusieurs
mêmes fonctionnalités que d'autres langages de programmation, tels que Kotlin et Swift, et peut être
trans-compilée en code JavaScript.
Flutter est différent des autres frameworks car il n'utilise ni WebView ni les widgets OEM fournis
avec l'appareil. Au lieu de cela, il utilise son propre moteur de rendu haute performance pour
dessiner des widgets. Il implémente également la plupart de ses systèmes tels que l'animation, les
gestes et les widgets dans le langage de programmation Dart qui permet aux développeurs de lire,
modifier, remplacer ou supprimer facilement des éléments. Il donne un excellent contrôle aux
développeurs sur le système.
• Flutter réduit le temps et les efforts de test. Comme nous le savons, les applications Flutter
sont multiplateformes, de sorte que les testeurs n'ont pas toujours besoin d'exécuter le même
ensemble de tests sur différentes plates-formes pour la même application.
• Il possède une excellente interface utilisateur car il utilise un widget centré sur la
conception, des outils de développement élevé, des API avancées et bien d'autres
fonctionnalités.
• Il est similaire à un cadre réactif dans lequel les développeurs n'ont pas besoin de mettre à
jour le contenu de l'interface utilisateur manuellement.
• Il convient aux applications MVP (Minimum Viable Product) en raison de son processus de
développement rapide et de sa nature multiplateforme.
• Il fournit un accès très limité aux bibliothèques SDK. Cela signifie qu'un développeur n'a
pas beaucoup de fonctionnalités pour créer une application mobile.
• Les applications Flutter ne prennent pas en charge le navigateur. Il ne prend en charge que
les plates-formes Android et iOS.
2. Architecture de Flutter
1. Moteur Flutter
2. Bibliothèque de la Fondation
3. Widgets
4. Concevoir des widgets spécifiques
Moteur Flutter :
Il s'agit d'un runtime portable pour les applications mobiles de haute qualité et principalement basé
sur le langage C ++. Il implémente les bibliothèques principales de Flutter qui incluent l'animation
et les graphiques, les E / S de fichiers et de réseau, l'architecture de plug-in, la prise en charge de
l'accessibilité et un environnement d'exécution de fléchettes pour le développement, la compilation
et l'exécution d'applications Flutter. Il faut la bibliothèque graphique open source de Google, Skia,
pour restituer des graphiques de bas niveau.
Bibliothèque de la Fondation :
Il contient tous les packages requis pour les éléments de base de l'écriture d'une application Flutter.
Ces bibliothèques sont écrites en langage Dart.
Widgets :
Dans Flutter, tout est un widget, qui est le concept central de ce framework. Widget dans le Flutter
est essentiellement un composant d'interface utilisateur qui affecte et contrôle la vue et l'interface de
l'application. Il représente une description immuable d'une partie de l'interface utilisateur et
comprend des graphiques, du texte, des formes et des animations créés à l'aide de widgets. Les
widgets sont similaires aux composants React.
Dans Flutter, l'application est elle-même un widget qui contient de nombreux sous-widgets.
Dans l'exemple ci-dessus, nous pouvons voir que tous les composants sont des widgets qui
contiennent des widgets enfants. Ainsi, l'application Flutter est elle-même un widget.
Couches
Le framework Flutter est catégorisé en fonction de sa complexité et établit une hiérarchie basée sur
le niveau décroissant de ces complexités. Ces catégories sont souvent appelées "couches". Ces
couches sont construites les unes sur les autres. La couche supérieure est un widget spécifique au
système d'exploitation de l'appareil (c'est-à-dire Android ou iOS). La deuxième couche est
constituée des widgets natifs de Flutter, qui comprennent les composants structurels de l'interface
utilisateur, les détecteurs de gestes, les composants de gestion d'état, etc. C'est dans cette troisième
couche que s'effectue le rendu de l'interface utilisateur et de l'état. C'est la couche qui comprend
tous les composants visibles de l'application Flutter. La couche suivante est constituée des
animations utilisées dans les transitions, le flux d'images et les gestes. Ces couches se poursuivent à
un niveau très élevé de la conception du système qui n'est pas l'objet de cet article. Le diagramme
ci-dessous en donne un aperçu :
Programmin It uses Dart language to create a mobile It uses JavaScript to create mobile
g Language app. apps.
User It uses custom widgets to build the UI of It uses native UI controllers to create
Interface the app. UI of the app.
4. Premier Application
Nous allons apprendre à créer une application simple dans Android Studio/Intellij pour comprendre
les bases de l'application Flutter.
Vérifions la structure de l'application du projet Flutter et son objectif. Dans l'image ci-dessous, vous
pouvez voir les différents dossiers et composants de la structure de l'application Flutter, qui vont
être abordés ici.
idea: ce dossier est tout en haut de la structure du projet, qui contient la configuration pour Android
Studio. Cela n'a pas d'importance car nous n'allons pas travailler avec Android Studio afin que le
contenu de ce dossier puisse être ignoré.
.android: ce dossier contient un projet Android complet et est utilisé lorsque vous créez l'application
Flutter pour Android. Lorsque le code Flutter est compilé dans le code natif, il est injecté dans ce
projet Android, de sorte que le résultat est une application Android native. Par exemple: lorsque
vous utilisez l'émulateur Android, ce projet Android est utilisé pour créer l'application Android, qui
s'est ensuite déployée sur le périphérique virtuel Android.
.ios: ce dossier contient un projet Mac complet et est utilisé lorsque vous créez l'application Flutter
pour iOS. Il est similaire au dossier Android utilisé lors du développement d'une application pour
Android. Lorsque le code Flutter est compilé dans le code natif, il est injecté dans ce projet iOS, de
sorte que le résultat est une application iOS native. La création d'une application Flutter pour iOS
n'est possible que lorsque vous travaillez sur macOS.
.lib: C'est un dossier essentiel, qui représente la bibliothèque. C'est un dossier dans lequel nous
effectuerons nos 99% de travail de projet. Dans le dossier lib, nous trouverons les fichiers Dart qui
contiennent le code de notre application Flutter. Par défaut, ce dossier contient le fichier [Link],
qui est le fichier d'entrée de l'application Flutter.
.test: ce dossier contient un code Dart, qui est écrit pour que l'application Flutter effectue le test
automatisé lors de la création de l'application.
.gitignore: C'est un fichier texte contenant une liste de fichiers, d'extensions de fichiers et de
dossiers qui indique à Git quels fichiers doivent être ignorés dans un projet. Git est un fichier de
contrôle de version permettant de suivre les modifications du code source lors du développement
logiciel Git.
.metadata: il s'agit d'un fichier généré automatiquement par les outils Flutter, qui est utilisé pour
suivre les propriétés du projet Flutter. Ce fichier effectue les tâches internes, vous n'avez donc pas
besoin de modifier le contenu manuellement à tout moment.
.packages: il s'agit d'un fichier généré automatiquement par le SDK Flutter, qui est utilisé pour
contenir une liste de dépendances pour votre projet Flutter.
flutter_demoapp.iml: Il est toujours nommé en fonction du nom du projet Flutter qui contient des
paramètres supplémentaires du projet. Ce fichier exécute les tâches internes, qui sont gérées par le
SDK Flutter, vous n'avez donc pas besoin de modifier le contenu manuellement à tout moment.
[Link]: C'est le fichier de configuration du projet qui sera beaucoup utilisé lors de
l'utilisation du projet Flutter. Il vous permet de savoir comment fonctionne votre application. Ce
fichier contient:
[Link]: C'est un fichier généré automatiquement basé sur le fichier .yaml. Il contient une
configuration plus détaillée sur toutes les dépendances.
[Link]: C'est un fichier généré automatiquement qui contient des informations sur le projet.
Nous pouvons éditer ce fichier si nous voulons partager des informations avec les développeurs.
Le fichier [Link] :
import 'package:flutter/[Link]';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text([Link]),
),
body: Center(
child: Text('Hello World'),
),
);
}
}
5. Le langage Dart
Dart est un langage de programmation open source, polyvalent et orienté objet avec une syntaxe de
style C développé par Google en 2011. Le but de la programmation Dart est de créer une interface
utilisateur frontale pour les applications Web et mobiles. Il est en cours de développement actif,
compilé en code machine natif pour la création d'applications mobiles, inspiré par d'autres langages
de programmation tels que Java, JavaScript, C # et est fortement typé. Puisque Dart est un langage
compilé, vous ne pouvez donc pas exécuter votre code directement; à la place, le compilateur
l'analyse et le transfère dans le code machine.
Il prend en charge la plupart des concepts courants des langages de programmation tels que les
classes, les interfaces, les fonctions, contrairement aux autres langages de programmation. Le
langage Dart ne prend pas en charge les tableaux directement. Il prend en charge la collection, qui
est utilisée pour répliquer la structure de données comme les tableaux, les génériques et le typage
facultatif.
Les variables :
Même dans un code Dart à sécurité de type, vous pouvez déclarer la plupart des variables sans
spécifier explicitement leur type à l'aide de var. Grâce à l'inférence de type, les types de ces
variables sont déterminés par leurs valeurs initiales :
var image = {
'tags': ['saturn'],
'url': '//path/to/[Link]'
};
int age = 20 ;
Late variables :
void main() {
description = 'Feijoada!';
print(description);
}
Variables Finale :
Si vous n'avez jamais l'intention de modifier une variable, utilisez final ou const, soit à la place de
var, soit en plus d'un type. Une variable final ne peut être définie qu'une seule fois ; une variable
const est une constante à la compilation. (Les variables const sont implicitement finales).
Les branches :
if (isRaining()) {
[Link]();
} else if (isSnowing()) {
[Link]();
} else {
[Link]();
}
// switch case :
Les boucles :
void main() {
int j = 0 ;
while(j < 10){
print('hello ${j+ 1}');
j++ ;
}
}
Les Collections
Dart prend en charge les collections de listes, d'ensembles et de cartes. Pour en savoir plus sur la
configuration des types que contiennent les collections.
Listes : La collection la plus courante dans presque tous les langages de programmation est le
tableau, ou groupe ordonné d'objets. Dans Dart, les tableaux sont des objets List, et la plupart des
gens les appellent donc simplement des listes.
var list = [
'Car',
'Boat',
'Plane',
];
Sets :
Dans Dart, un ensemble est une collection non ordonnée d'éléments uniques. Le support Dart pour
les ensembles est fourni par les littéraux d'ensemble et le type Set.
Maps : En général, une map est un objet qui associe des clés et des valeurs. Les clés et les valeurs
peuvent être n'importe quel type d'objet. Chaque clé n'apparaît qu'une seule fois, mais vous pouvez
utiliser la même valeur plusieurs fois. La prise en charge des maps par Dart est assurée par les
littéraux de map et le type Map.
var nobleGases = {
2: 'helium',
10: 'neon',
18: 'argon',
};
[Link]((key, value) {
print([Link]() + " , "+ [Link]());
});
gifts['second'] = 'turtledoves';
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';
Les Fonctions :
//Function declaration
isNoble(atomicNumber) {
return _nobleGases[atomicNumber] != null;
For functions that contain just one expression, you can use a shorthand syntax:
void enableFlags({bool bold = false, bool hidden = false}) {…} //value by default
Programmation orientée objet :
class Mobile {
//PropertyDeclaration
String color, brandName, modelName;
//MethodCreation
String calling() {
return "Mobilecandocalltoeveryone.";
}
String musicPlay() {
return "MobilecanplayalltypesofMusic.";
}
String clickPicture() {
return "Mobilecantakepictures.";
}
}
void main() {
//ObjectCreation
var myMob = new Mobile("Black", "AppleInc.", "iPhone11Pro");
//DisplayOutput
print([Link]);
print([Link]);
print([Link]);
print([Link]());
print([Link]());
print([Link]());
}
Impératif
Le paradigme impératif est un ensemble d'instructions que vous donnez à l'ordinateur. Vous donnez
les étapes détaillées de l'exécution d'un programme. Voyons cela à l'aide d'un exemple.
Énoncé du problème : Vous avez une liste de nombres et vous voulez trouver tous les nombres
pairs.
void main(List<String> args) {
final _result = [];
final _number = [1, 2, 3, 4, 5, 6, 7, 8];
Déclaratif
Le paradigme déclaratif indique au programme ce qu'il veut. Il se concentre sur le "Quoi" plutôt que
sur le "Comment". Cela permet de rendre le code plus raisonnable.
print(_result);
}
Maintenant, vous dites au programme ce que vous voulez. De plus, vous ne modifiez plus aucun
état.
Si nous comparons les deux extraits, vous observerez que pour l'impératif, nous devons parcourir la
boucle, l'exécuter mentalement en pensant à ce qu'elle fait, et ensuite nous comprenons le code. En
revanche, le code déclaratif ressemble à de la prose bien écrite (on peut encore l'améliorer en
convertissant number % 2 == 0 en une fonction isEven distincte).
La programmation fonctionnelle (aka. FP ) est une manière déclarative d'écrire des programmes, où
un programme est composé de fonctions. Cette définition prendra tout son sens lorsque nous
aborderons certaines terminologies de la programmation fonctionnelle.
Dans Dart, les fonctions sont traitées comme des citoyens de première classe (First class function),
ce qui signifie que les fonctions sont traitées comme n'importe quelles autres valeurs telles que
String, int, bool, etc. On peut passer des fonctions comme arguments, les assigner à une variable et
renvoyer des fonctions comme résultat.
bool isOddNumber(int x) {
return x % 2 != 0;
}
bool isEvenNumber(int x) {
return x % 2 == 0;
}
void main() {
print("Even numbers:");
show(isEvenNumber);
print("Odd numbers:");
show(isOddNumber);
}
add(int x, int y) {
return x + y;
}
subtract(int x, int y) {
return x - y;
}
void main() {
var fn = calculation('+');
print(fn(10, 20));
fn = calculation('-');
print(fn(30,20));
}
Fonctions d'ordre supérieur (HOF)
Une fonction qui prend une fonction comme argument ou qui renvoie une fonction est une fonction
d'ordre supérieur. Cela est possible parce que les fonctions sont traitées comme des citoyens de
première classe dans Dart.
Vous avez déjà utilisé des fonctions d'ordre supérieur si vous avez utilisé des méthodes de tableau
intégrées telles que where, map ou reduce.
Filtre(where) :
Le filtre prend une fonction prédicat et un tableau et renvoie une nouvelle liste contenant
uniquement les valeurs pour lesquelles la fonction prédicat renvoie vrai.
Imaginez que vous écriviez un programme pour filtrer tous les nombres pairs de la liste.
print(_result_ov);
}
Map :
La Map fonctionne de la même manière qu'un filtre, sauf qu'au lieu de prendre une fonction
prédicat, elle prend une fonction mappeur, l'applique à chaque élément de la liste et renvoie une
nouvelle liste.
Imaginez que vous écriviez un programme pour doubler tous les éléments de la liste.
print(result);
}
Réduire :
Elle réduit une collection en une seule valeur en combinant tous les éléments à l'aide de la fonction
passée.
print(result);
}
• Il est plus facile de raisonner sur le code. Le code devient plus concis et plus expressif. Un
code raisonnable est plus facile à maintenir.
• Il favorise la modularité et est hautement composable.
• Il divise le problème en petits morceaux.
• Il aide à augmenter les performances par des exécutions parallèles, la mémoïsation et
d'autres techniques (que nous allons couvrir).
• Il est plus facile d'écrire des tests et facilite le débogage.
Les widgets sont imbriqués les uns avec les autres pour créer l'application. Cela signifie que la
racine de votre application est elle-même un widget, et tout en bas est également un widget. Par
exemple, un widget peut afficher quelque chose, définir le design, gérer l'interaction, etc.
L'image ci-dessous est une représentation visuelle simple de l'arborescence des widgets.
Classe de conteneur dans Flutter
La classe Container de Flutter est un widget de commodité qui combine les fonctions courantes de
peinture, de positionnement et de dimensionnement des widgets. Une classe Container peut être
utilisée pour stocker un ou plusieurs widgets et les positionner sur l'écran à notre convenance.
Fondamentalement, un conteneur est comme une boîte dans laquelle on stocke du contenu. Un
élément de conteneur de base qui stocke un widget possède une marge, qui sépare le conteneur
actuel des autres contenus. L'ensemble du conteneur peut être entouré d'une bordure de différentes
formes, par exemple des rectangles arrondis, etc. Un conteneur entoure son enfant avec un
rembourrage et applique ensuite des contraintes supplémentaires à l'étendue du rembourrage (en
incorporant la largeur et la hauteur en tant que contraintes, si l'une ou l'autre n'est pas nulle).
import 'package:flutter/[Link]';
void main() {
runApp(const GFGapp());
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'GeeksforGeeks',
theme: ThemeData(primarySwatch: [Link]),
darkTheme: ThemeData(primarySwatch: [Link]),
color: [Link],
supportedLocales: {const Locale('en', ' ')},
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(title: const Text('GeeksforGeeks')),
),
);
}
}
Afin d'utiliser le tiroir d'application, vous devez importer le paquet de composants matériels qui est
"package : flutter/[Link]".
L'AppDrawer de navigation est divisé en trois sections : l'en-tête, le corps et le pied de page. L'idée
est d'avoir un navigateur avec quelques éléments en tant qu'enfants du tiroir qui seront dirigés vers
différentes destinations lorsqu'on les touchera. Tous les enfants d'un widget Drawer sont
généralement dans un ListView et, initialement, seul le DrawerHeader est présent dans l'interface
utilisateur qui s'étend horizontalement lorsqu'on le touche.
import 'package:flutter/[Link]';
@override
Widget build(BuildContext context) {
return MaterialApp(
title: appTitle,
home: MyHomePage(title: appTitle),
); // MaterialApp
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
backgroundColor: [Link],
),
body: const Center(
child: Text(
'A drawer is an invisible side screen.',
style: TextStyle(fontSize: 20.0),
)),
drawer: Drawer(
child: ListView(
padding: const [Link](0),
children: [
const DrawerHeader(
decoration: BoxDecoration(
color: [Link],
), //BoxDecoration
child: UserAccountsDrawerHeader(
decoration: BoxDecoration(color: [Link]),
accountName: Text(
"Abhishek Mishra",
style: TextStyle(fontSize: 18),
),
accountEmail: Text("abhishekm977@[Link]"),
currentAccountPictureSize: [Link](50),
currentAccountPicture: CircleAvatar(
backgroundColor: [Link](255, 165, 255, 137),
child: Text(
"A",
style: TextStyle(fontSize: 30.0, color: [Link]),
), //Text
), //circleAvatar
), //UserAccountDrawerHeader
), //DrawerHeader
ListTile(
leading: const Icon([Link]),
title: const Text(' My Profile '),
onTap: () {
[Link](context);
},
),
ListTile(
leading: const Icon([Link]),
title: const Text(' My Course '),
onTap: () {
[Link](context);
},
),
ListTile(
leading: const Icon(Icons.workspace_premium),
title: const Text(' Go Premium '),
onTap: () {
[Link](context);
},
),
ListTile(
leading: const Icon(Icons.video_label),
title: const Text(' Saved Videos '),
onTap: () {
[Link](context);
},
),
ListTile(
leading: const Icon([Link]),
title: const Text(' Edit Profile '),
onTap: () {
[Link](context);
},
),
ListTile(
leading: const Icon([Link]),
title: const Text('LogOut'),
onTap: () {
[Link](context);
},
),
],
),
), //Drawer
);
}
}
AppBar est généralement le composant le plus haut de l'application (ou parfois le plus bas), il
contient la barre d'outils et d'autres boutons d'action communs. Comme tous les composants d'une
application Flutter sont des widgets ou des combinaisons de widgets, l'AppBar est également une
classe ou un widget intégré dans Flutter. AppBar est donc également une classe intégrée ou un
widget dans Flutter qui donne la fonctionnalité de l'AppBar dès le départ. Le widget AppBar est
basé sur le Material Design et la plupart des informations sont déjà fournies par d'autres classes
comme MediaQuery, Scaffold, quant à l'endroit où le contenu de l'AppBar doit être placé. Bien que
la classe AppBar soit très flexible et puisse être facilement personnalisée, nous pouvons également
utiliser le widget SliverAppBar qui donne une fonctionnalité de défilement à la barre d'application.
Nous pouvons également créer notre propre barre d'application personnalisée à partir de zéro.
import 'package:flutter/[Link]';
void main() {
runApp(gfgApp()); //MaterialApp
}
MaterialApp gfgApp() {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('GeeksforGeeks'),
), //AppBar
body: const Center(
child: Text(
'GeeksforGeeks',
style: TextStyle(fontSize: 24),
), //Text
), // center
), //Scaffold
debugShowCheckedModeBanner: false, //Removing Debug Banner
);
}
Types de widget
Widget visible :
Les widgets visibles sont liés aux données d'entrée et de sortie de l'utilisateur. Certains des types
importants de ce widget sont:
Text :
Un widget Texte contient du texte à afficher à l'écran. Nous pouvons aligner le widget de texte en
utilisant la propriété textAlign, et la propriété style permet la personnalisation du texte qui inclut la
police, l'épaisseur de la police, le style de police, l'espacement des lettres, la couleur et bien d'autres.
Nous pouvons l'utiliser comme ci-dessous des extraits de code.
new Text(
'Hello, Javatpoint!',
textAlign: [Link],
style: new TextStyle(fontWeight: [Link]),
)
TextField
TextField et TextFormField sont les deux widgets les plus courants pour obtenir les commentaires
de l'utilisateur. Ils peuvent être utilisés pour créer des formulaires, des pages de connexion, etc. Afin
de rendre leur mise en œuvre efficace et précise, nous devons ajouter certaines fonctionnalités.
Declaration de varable _b
num _b ; au niveau de la class
TextField(
decoration: const InputDecoration(labelText: 'Number b :'),
keyboardType: [Link],
onChanged: (value){
setState(() {
_b = [Link](value) ;
});
},
Button:
Ce widget vous permet d'effectuer une action au clic. Flutter ne vous permet pas d'utiliser
directement le widget Button; à la place, il utilise un type de boutons comme un FlatButton et un
RaisedButton. Nous pouvons l'utiliser comme ci-dessous des extraits de code.
//FlatButton Example
new FlatButton(
child: Text("Click here"),
onPressed: () {
// Do something here
},
),
//RaisedButton Example
new RaisedButton(
child: Text("Click here"),
elevation: 5.0,
onPressed: () {
// Do something here
},
),
Dans l'exemple ci-dessus, la propriété onPressed nous permet d'effectuer une action lorsque vous
cliquez sur le bouton, et la propriété d'élévation est utilisée pour changer la façon dont elle se
démarque.
Image :
Ce widget contient l'image qui peut la récupérer à partir de plusieurs sources, telles que le dossier
d'actifs ou directement à partir de l'URL. Il fournit de nombreux constructeurs pour charger l'image,
qui sont donnés ci-dessous:
Pour ajouter une image dans le projet, vous devez d'abord créer un dossier de ressources dans lequel
vous stockez vos images, puis ajouter la ligne ci-dessous dans le fichier [Link].
assets:
- assets/
[Link]('assets/[Link]')
Widget invisible
Les widgets invisibles sont liés à la disposition et au contrôle des widgets. Il permet de contrôler le
comportement réel des widgets et leur apparence à l'écran. Certains des types importants de ces
widgets sont:
Column :
Un widget de colonne est un type de widget qui organise tous les widgets de ses enfants dans un
alignement vertical. Il fournit un espacement entre les widgets à l'aide des propriétés
mainAxisAlignment et crossAxisAlignment. Dans ces propriétés, l'axe principal est l'axe vertical et
l'axe transversal est l'axe horizontal.
new Column(
mainAxisAlignment: [Link],
children: <Widget>[
new Text(
"VegElement",
),
new Text(
"Non-vegElement"
),
],
),
Ligne « Row » :
Le widget de ligne est similaire au widget de colonne, mais il construit un widget horizontalement
plutôt que verticalement. Ici, l'axe principal est l'axe horizontal et l'axe transversal est l'axe vertical.
new Row(
mainAxisAlignment: [Link],
children: <Widget>[
new Text(
"VegElement",
),
new Text(
"Non-vegElement"
),
],
),
Center :
Ce widget est utilisé pour centrer le widget enfant, qui vient à l'intérieur. Tous les exemples
précédents contiennent à l'intérieur du widget central.
Center(
Padding :
Ce widget enveloppe les autres widgets pour leur donner un remplissage dans des directions
spécifiées. Vous pouvez également fournir un rembourrage dans toutes les directions. Nous pouvons
le comprendre à partir de l'exemple ci-dessous qui donne au widget texte un remplissage de 6.0
dans toutes les directions.
Padding(
Stack :
C'est un widget essentiel, qui est principalement utilisé pour superposer un widget, comme un
bouton sur un dégradé d'arrière-plan.
• StatelessWidget
• StatefulWidget
StatefulWidget
Un StatefulWidget a des informations d'état. Il contient principalement deux classes: l'objet d'état et
le widget. Il est dynamique car il peut modifier les données internes pendant la durée de vie du
widget. Ce widget n'a pas de méthode build (). Il a la méthode createState (), qui retourne une classe
qui étend la classe d'état Flutters. Les exemples de StatefulWidget sont Checkbox, Radio, Slider,
InkWell, Form et TextField.
@override
_CarState createState() => _CarState();
}
StatelessWidget :
Le StatelessWidget ne dispose d'aucune information d'état. Il reste statique tout au long de son cycle
de vie. Les exemples du StatelessWidget sont Text, Row, Column, Container, etc.
@override
Widget build(BuildContext context) {
return Container(color: const Color(0x0xFEEFE));
}
}
Dans l'image ci-dessus, le conteneur est une classe de widget qui nous permet de personnaliser le
widget enfant. Il est principalement utilisé pour ajouter des bordures, un remplissage, des marges,
une couleur d'arrière-plan et bien d'autres. Ici, le widget texte vient sous le conteneur pour ajouter
des marges. La ligne entière est également placée dans un conteneur pour ajouter une marge et un
remplissage autour de la ligne. En outre, le reste de l'interface utilisateur est contrôlé par des
propriétés telles que la couleur, le [Link], etc.
Le widget de mise en page enfant unique est un type de widget, qui ne peut avoir qu'un seul widget
enfant à l'intérieur du widget de mise en page parent. Ces widgets peuvent également contenir des
fonctionnalités de mise en page spéciales. Flutter nous fournit de nombreux widgets pour enfant
unique pour rendre l'interface utilisateur de l'application attrayante. Si nous utilisons ces widgets de
manière appropriée, cela peut nous faire gagner du temps et rendre le code de l'application plus
lisible. La liste des différents types de widgets enfant unique est:
Container : c'est le widget de mise en page le plus populaire qui fournit des options personnalisables
pour la peinture, le positionnement et le dimensionnement des widgets.
Center(
child: Container(
margin: const [Link](15.0),
color: [Link],
width: 42.0,
height: 42.0,
),
)
Padding : C'est un widget qui est utilisé pour organiser son widget enfant par le remplissage donné.
Il contient EdgeInsets et [Link] pour le côté souhaité où vous souhaitez fournir un
remplissage.
const Greetings(
child: Padding(
padding: [Link](14.0),
child: Text('Hello JavaTpoint!'),
),
)
Align : il s'agit d'un widget, qui aligne son widget enfant en lui-même et le dimensionne en fonction
de la taille de l'enfant. Il offre plus de contrôle pour placer le widget enfant à la position exacte où
vous en avez besoin.
Center(
child: Container(
height: 110.0,
width: 110.0,
color: [Link],
child: Align(
alignment: [Link],
child: FlutterLogo(
size: 50,
),
),
),
)
SizedBox: Ce widget vous permet de donner la taille spécifiée au widget enfant à travers tous les
écrans.
SizedBox(
width: 300.0,
height: 450.0,
child: const Card(child: Text('Hello JavaTpoint!')),
)
import 'package:flutter/[Link]';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("FittedBox Widget")),
body: Center(
child: FittedBox(child: Row(
children: <Widget>[
Container(
child: [Link]('assets/[Link]'),
),
Container(
child: Text("This is a widget"),
)
],
),
fit: [Link],
)
),
);
}
}
Les widgets enfants multiples sont un type de widget, qui contient plusieurs widgets enfants, et la
disposition de ces widgets est unique. Par exemple, le widget Row disposant de son widget enfant
dans une direction horizontale, et le widget Column disposant de son widget enfant dans une
direction verticale. Si nous combinons le widget Ligne et Colonne, alors il peut construire n'importe
quel niveau du widget complexe.
Row: Il permet d'organiser ses widgets enfants dans une direction horizontale.
import 'package:flutter/[Link]';
),
Expanded(
child: FittedBox(
fit: [Link], // otherwise the logo will be tiny
child: const FlutterLogo(),
),
),
],
),
),
);
}
}
Column: Elle permet d'organiser ses widgets enfants dans une direction verticale.
ListView: C'est le widget de défilement le plus populaire qui nous permet d'organiser ses widgets
enfants les uns après les autres dans le sens du défilement.
GridView: Il nous permet d'organiser ses widgets enfants sous la forme d'un tableau 2D déroulant
de widgets. Il se compose d'un motif répété de cellules disposées dans une disposition horizontale et
verticale.
Expanded: Il permet de faire en sorte que les enfants d'un widget Ligne et Colonne occupent le
maximum de surface possible.
Table: C'est un widget qui nous permet d'organiser ses enfants dans un widget basé sur une table.
Stack : C'est un widget essentiel, qui est principalement utilisé pour superposer plusieurs widgets
enfants. Il vous permet de mettre en place les multiples couches sur l'écran. L'exemple suivant aide
à le comprendre.
import 'package:flutter/[Link]';
Voyons un exemple d'interface utilisateur complexe en créant la liste de produits. Pour cela, vous
devez d'abord remplacer le code du fichier [Link] par l'extrait de code suivant.
import 'package:flutter/[Link]';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Product List")),
body: ListView(
padding: const [Link](3.0, 12.0, 3.0, 12.0),
children: <Widget>[
ProductBox(
name: "iPhone",
description: "iPhone is the top branded phone ever",
price: 55000,
image: "[Link]"
),
ProductBox(
name: "Android",
description: "Android is a very stylish phone",
price: 10000,
image: "[Link]"
),
ProductBox(
name: "Tablet",
description: "Tablet is a popular device for official meetings",
price: 25000,
image: "[Link]"
),
ProductBox(
name: "Laptop",
description: "Laptop is most famous electronic device",
price: 35000,
image: "[Link]"
),
ProductBox(
name: "Desktop",
description: "Desktop is most popular for regular use",
price: 10000,
image: "[Link]"
),
],
)
);
}
}
class ProductBox extends StatelessWidget {
ProductBox({Key key, [Link], [Link], [Link], [Link]}) :
super(key: key);
final String name;
final String description;
final int price;
final String image;
Dans le code ci-dessus, nous créons le widget ProductBox qui contient les détails du produit, tels
que l'image, le nom, le prix et la description. Dans le widget ProductBox, nous utilisons les widgets
enfants suivants: Conteneur, Ligne, Colonne, Développé, Carte, Texte, Image, etc. Ce widget
contient la mise en page suivante:
Les gestes sont une fonctionnalité intéressante de Flutter qui nous permet d'interagir avec
l'application mobile (ou tout appareil tactile). D'une manière générale, les gestes définissent toute
action physique ou mouvement d'un utilisateur dans l'intention d'un contrôle spécifique de l'appareil
mobile. Certains des exemples de gestes sont:
• Lorsque l'écran du mobile est verrouillé, vous faites glisser votre doigt sur l'écran pour le
déverrouiller.
• En appuyant sur un bouton sur l'écran de votre mobile
• Appuyez et maintenez une icône d'application sur un appareil tactile pour la faire glisser sur
les écrans.
Nous utilisons tous ces gestes dans la vie de tous les jours pour interagir avec votre téléphone ou
appareil tactile.
Flutter divise le système gestuel en deux couches différentes, qui sont données ci-dessous:
• Pointeurs
• Gestes
Les Pointeurs :
Les pointeurs sont la première couche qui représente les données brutes sur l'interaction de
l'utilisateur. Il contient des événements qui décrivent l'emplacement et le mouvement des pointeurs
tels que les touches, les souris et le style sur les écrans. Flutter ne fournit aucun mécanisme pour
annuler ou arrêter les événements de pointeur d'être distribués davantage. Flutter fournit un widget
Listener pour écouter les événements de pointeur directement à partir de la couche de widgets. Les
événements-pointeurs sont des catégories en quatre types principaux:
• PointerDownEvents
• PointerMoveEvents
• PointerUpEvents
• PointeurAnnulerEvénements
PointerCancelEvents: cet événement est envoyé lorsque l'interaction du pointeur est annulée.
Les Gestes :
C'est la deuxième couche qui représente les actions sémantiques telles que toucher, glisser et mettre
à l'échelle, qui sont reconnues à partir de plusieurs événements de pointeur individuels. Il est
également capable de distribuer plusieurs événements correspondant au cycle de vie des gestes tels
que le début du glissement, le glissement de la mise à jour et le glissement de la fin. Certains des
gestes couramment utilisés sont répertoriés ci-dessous:
Tap : Cela signifie toucher la surface de l'écran du bout du doigt pendant une courte période, puis
les relâcher. Ce geste contient les événements suivants:
• onTapDown
• onTapUp
• onTap
• onTapCancel
Double Tap: Cela ressemble à un geste Tap, mais vous devez appuyer deux fois en peu de temps. Ce
geste contient les événements suivants:
• onDoubleTap
Glisser: Cela nous permet de toucher la surface de l'écran avec un doigt et de le déplacer d'un
endroit à un autre, puis de les relâcher. Flutter classe le glissement en deux types:
Glissement vertical: ce geste permet au pointeur de se déplacer dans une direction verticale. Il
contient les événements suivants:
• onVerticalDragStart
• onVerticalDragStart
• onVerticalDragStart
Appui long: cela signifie toucher la surface de l'écran à un endroit particulier pendant une longue
période. Ce geste contient les événements suivants:
• onLongPress
Pan: Cela signifie toucher la surface de l'écran avec un doigt, qui peut se déplacer dans n'importe
quelle direction sans relâcher le bout du doigt. Ce geste contient les événements suivants:
• onPanStart
• onPanUpdate
• onPanEnd
Pinch: Cela signifie pincer (déplacer son doigt et son pouce ou les rapprocher sur un écran tactile) la
surface de l'écran à l'aide de deux doigts pour effectuer un zoom avant ou arrière sur un écran.
Détecteur de gestes :
import 'package:flutter/[Link]';
import 'package:flutter/[Link]';
import 'package:flutter/[Link]';
Dans Flutter, les écrans et les pages sont appelés itinéraires, et ces itinéraires ne sont qu'un widget.
Sous Android, un itinéraire est similaire à une activité, alors que, sous iOS, il équivaut à un
ViewController.
Dans toute application mobile, la navigation vers différentes pages définit le flux de travail de
l'application et la manière de gérer la navigation est appelée routage. Flutter fournit une classe de
routage de base MaterialPageRoute et deux méthodes [Link] () et [Link] () qui
montrent comment naviguer entre deux routes. Les étapes suivantes sont nécessaires pour démarrer
la navigation dans votre application.
import 'package:flutter/[Link]';
void main() {
runApp(MaterialApp(
title: 'Flutter Navigation',
theme: ThemeData(
// This is the theme of your application.
primarySwatch: [Link],
),
home: FirstRoute(),
));
}
import 'package:flutter/[Link]';
void main() {
runApp( MaterialApp(
title: 'Named Route Navigation',
theme: ThemeData(
// This is the theme of your application.
primarySwatch: [Link],
),
// Start the app with the "/" named route. In this case, the app starts
// on the FirstScreen widget.
initialRoute: '/',
routes: {
// When navigating to the "/" route, build the FirstScreen widget.
'/': (context) => HomeScreen(),
// When navigating to the "/second" route, build the SecondScreen widget.
'/second': (context) => SecondScreen(),
},
));
}
9. Flutter et Sqlite :
Si vous écrivez une application qui doit persister et interroger de grandes quantités de données sur
l'appareil local, envisagez d'utiliser une base de données au lieu d'un fichier local ou d'un magasin
de valeurs clés. En général, les bases de données permettent des insertions, des mises à jour et des
requêtes plus rapides que les autres solutions de persistance locales.
Les applications Flutter peuvent utiliser les bases de données SQLite via le plugin sqflite disponible
sur [Link]. Cette recette démontre les bases de l'utilisation de sqflite pour insérer, lire, mettre à
jour et supprimer des données sur divers objets.
Pour travailler avec des bases de données SQLite, importez les paquets sqflite et path.
Le paquet sqflite fournit des classes et des fonctions permettant d'interagir avec une base de
données SQLite.
Le paquet path fournit des fonctions permettant de définir l'emplacement de stockage de la base de
données sur le disque.
import 'dart:async';
import 'package:flutter/[Link]';
import 'package:path/[Link]';
import 'package:sqflite/[Link]';
class Personne {
final int id;
final String name;
final int age;
const Dog({
required [Link],
required [Link],
required [Link],
});
}
• L'id est un int Dart, et est stocké en tant que type de données SQLite INTEGER. Il est
également conseillé d'utiliser l'identifiant comme clé primaire de la table afin d'améliorer les
temps de requête et de mise à jour.
• Le nom est une chaîne Dart et est stocké sous la forme d'un type de données TEXT SQLite.
• L'âge est également un Dart int, et est stocké sous la forme d'un type de données INTEGER.
Maintenant que vous disposez d'une base de données avec une table permettant de stocker des
informations sur différents personnes, il est temps de lire et d'écrire des données.
Tout d'abord, insérez un chien dans la table personnes . Cette opération comporte deux étapes :
class Personne {
final int id;
final String name;
final int age;
Personne({
required [Link],
required [Link],
required [Link],
});
// Convert a Personne into a Map. The keys must correspond to the names of the
// columns in the database.
Map<String, Object?> toMap() {
return {
'id': id,
'name': name,
'age': age,
};
}
// Insert the Personne into the correct table. You might also specify the
// `conflictAlgorithm` to use in case the same Personnes is inserted twice.
//
// In this case, replace any previous data.
await [Link](
'personnes',
[Link](),
conflictAlgorithm: [Link],
);
}
await insertPersonne(per);
Maintenant qu'une personne est stockée dans la base de données, interrogez la base de données pour
obtenir une personne spécifique ou une liste de toutes les personnes. Cette opération s'effectue en
deux étapes :
// A method that retrieves all the personnes from the personnes table.
Future<List<Personne>> personnes() async {
// Get a reference to the database.
final db = await database;
// Convert the list of each personne’s fields into a list of `Personnes` objects.
return [
for (final {
'id': id as int,
'name': name as String,
'age': age as int,
} in personneMaps)
Personne(id: id, name: name, age: age),
];
}
Outre l'insertion et la mise à jour d'informations sur les chiens, vous pouvez également supprimer
des personnes de la base de données. Pour supprimer des données, utilisez la méthode delete() de la
bibliothèque sqflite.
Dans cette section, créez une fonction qui prend un identifiant et supprime de la base de données le
chien dont l'identifiant correspond. Pour que cela fonctionne, vous devez fournir une clause where
afin de limiter les enregistrements à supprimer.
Le package http fournit également une classe de client http standard qui prend en charge la
connexion persistante. Cette classe est utile lorsque de nombreuses requêtes doivent être effectuées
sur un serveur particulier. Il doit être fermé correctement en utilisant la méthode close (). Sinon,
cela fonctionne comme une classe http. Le code suivant l'explique plus clairement.
try {
print(await [Link]('[Link]
}
finally {
[Link]();
}
Pour installer le package http, ouvrez le fichier [Link] dans le dossier de votre projet et
ajoutez le package http dans la section des dépendances.
[Link]
dependencies:
http: <latest_version>
La méthode Get :
Future<[Link]> fetchPost() {
return [Link]('[Link]
}
La méthode Post :
class Post {
if ([Link] == 200) {
// If the server returns an OK response, then parse the JSON.
return [Link]([Link]([Link]));
} else {
// If the response was umexpected, throw an error.
throw Exception('Failed to load post');
}
}
Exemple Complet :
import 'dart:async';
import 'dart:convert';
import 'package:flutter/[Link]';
import 'package:http/[Link]' as http;
void main() => runApp(MyApp());
@override
_MyAppState createState() => _MyAppState();
}
@override
void initState() {
[Link]();
post = fetchPost();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter REST API Example',
theme: ThemeData(
primarySwatch: [Link],
),
home: Scaffold(
appBar: AppBar(
title: Text('Flutter REST API Example'),
),
body: Center(
child: FutureBuilder<Post>(
future: post,
builder: (context, abc) {
if ([Link]) {
return Text([Link]);
} else if ([Link]) {
return Text("${[Link]}");
}
if ([Link] == 200) {
// If the call to the server was successful (returns OK), parse the JSON.
return [Link]([Link]([Link]));
} else {
// If that call was not successful (response was unexpected), it throw an error.
throw Exception('Failed to load post');
}
}
class Post {
final int userId;
final int id;
final String title;
final String description;
References :
[Link]
[Link]