Slide 1

Slide 1 text

Les Widgets en Flutter Edouard Marquez (Développeur freelance Flutter & Android)

Slide 2

Slide 2 text

Avant de commencer

Slide 3

Slide 3 text

Les Widgets en Flutter Devfest Lille 2019 En résumé, qu'est-ce que Flutter ? Framework permettant de concevoir des applications multiplateforme Smartphones Android et iOS Ordinateurs* Windows, Mac, Linux Embarqué Ex : Nest Hub Max Web* “ “

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Les Widgets en Flutter Devfest Lille 2019 Comment fonctionne Flutter ? Code natif Canvas Evénements Application Plateforme Position GPS Bluetooth Audio Capteurs Caméra Etc Services Widgets, Rendu Platform Channels

Slide 6

Slide 6 text

Les Widgets en Flutter Devfest Lille 2019 La stack Flutter Material Cupertino Widgets Rendering Fondation Animation Painting Gestures Framework (Dart) Skia Dart Text Engine (C++)

Slide 7

Slide 7 text

Les Widgets en Flutter Devfest Lille 2019 Du multiplateforme… mais natif et surtout pratique ! Dart Connait une deuxième vie grâce à Flutter Mode AOT Génération d'un binaire optimisé pour la plateforme Mode JIT Lors du développement, injection des changements à la volée Garbage collector Optimisé pour le recyclage de nombreux petits objets

Slide 8

Slide 8 text

Les Widgets en Flutter Devfest Lille 2019 Un développement agréable et rapide grâce au Hot Reload

Slide 9

Slide 9 text

Les Widgets

Slide 10

Slide 10 text

void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'Flutter Demo Home Page'), ); } }

Slide 11

Slide 11 text

void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'Flutter Demo Home Page'), ); } }

Slide 12

Slide 12 text

Une application est un Widget “ “

Slide 13

Slide 13 text

void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'Flutter Demo Home Page'), ); } }

Slide 14

Slide 14 text

void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'Flutter Demo Home Page'), ); } }

Slide 15

Slide 15 text

Qui elle même affiche des Widgets ? “ “

Slide 16

Slide 16 text

Oui, en Flutter Tout est un Widget “ “

Slide 17

Slide 17 text

Les Widgets expliqués

Slide 18

Slide 18 text

Ceci n'est pas une présentation sponsorisée

Slide 19

Slide 19 text

1 Il en existe de toutes les formes

Slide 20

Slide 20 text

1 Il en existe de toutes les formes 2 Une brique peut avoir plusieurs couleurs

Slide 21

Slide 21 text

1 Il en existe de toutes les formes 3 Une brique n'a qu'une seule fonction 2 Une brique peut avoir plusieurs couleurs

Slide 22

Slide 22 text

1 Il en existe de toutes les formes 4 On peut imbriquer une forme 
 dans une autre 2 Une brique peut avoir plusieurs couleurs 3 Une brique n'a qu'une seule fonction

Slide 23

Slide 23 text

1 Il en existe de toutes les formes 4 On peut imbriquer une forme 
 dans une autre 5 Ou au contraire… 
 certaines ne peuvent pas 2 Une brique peut avoir plusieurs couleurs 3 Une brique n'a qu'une seule fonction

Slide 24

Slide 24 text

1 Il en existe de toutes les formes 4 On peut imbriquer une forme 
 dans une autre 5 Ou au contraire… 
 certaines ne peuvent pas 6 On peut obtenir des résultats complexes 2 Une brique peut avoir plusieurs couleurs 3 Une brique n'a qu'une seule fonction

Slide 25

Slide 25 text

1 Il en existe de toutes les formes 2 Une brique peut avoir plusieurs couleurs 3 Une brique n'a qu'une seule fonction 4 On peut imbriquer une forme 
 dans une autre 5 Ou au contraire… 
 certaines ne peuvent pas 6 On peut obtenir des résultats complexes 7 Certaines briques sont utilitaires, d'autres visibles

Slide 26

Slide 26 text

Et appliqué à Flutter ?

Slide 27

Slide 27 text

1 Il existe de très nombreux Widgets Application Layout Widget 1 Widget 2 Widget 3 Stocker des informations { "User":"toto", "Password":"LOL" } Accessibilité Image d'un pont Texte Hello World ! Animation A B

Slide 28

Slide 28 text

1 Il existe de très nombreux Widgets flutter.dev Widgets catalog

Slide 29

Slide 29 text

Texte Hello World ! Le texte peut changer sa police Le texte peut changer sa couleur Le texte peut changer sa taille Le texte peut changer son alignement 2 Un Widget peut contenir des attributs

Slide 30

Slide 30 text

Texte Hello World ! Ne sait pas gérer le padding Ne sait pas la couleur d'arrière-plan Ne sait pas comment gérer l'opacité Ne sait pas comment scroller… 3 Mais un Widget est ultra-spécialisé

Slide 31

Slide 31 text

4 On peut imbriquer un Widget dans un autre Layout Widget 1 Widget 2 Widget 3 Le Widget Column peut accueillir plusieurs enfants qu'il alignera les uns en dessous des autres Padding Le Widget Padding peut accueillir une seul enfant sur lequel il appliquera des marges Hello World !

Slide 32

Slide 32 text

Texte Hello World ! 5 Ou au contraire… certains ne peuvent pas Image

Slide 33

Slide 33 text

6 On peut obtenir des résultats complexes

Slide 34

Slide 34 text

7 Certains Widgets ne dessinent rien à l'écran Layout Widget 1 Widget 2 Widget 3 Stocker des informations { "User":"toto", "Password":"LOL" } Accessibilité Image d'un pont Texte Hello World !

Slide 35

Slide 35 text

Si on résume

Slide 36

Slide 36 text

Les Widgets en Flutter Devfest Lille 2019 Un Widget en Flutter est donc… Description d'une partie de la UI Peut s'imbriquer à d'autres Widgets Fait partie d'un arbre de Widgets

Slide 37

Slide 37 text

Widget A Widget B Widget D Widget E Widget C Widget F Widget G

Slide 38

Slide 38 text

Mise en application

Slide 39

Slide 39 text

Analytics Want to see about : Audience 260 Total Posts 26.84% 2.648 Followers 26.32% 768 Followers 0.86% 82.6% Engagement 8.64%

Slide 40

Slide 40 text

Les Widgets en Flutter Devfest Lille 2019 Imbriquer des Widgets grâce au StatelessWidget 260 Total Posts 26.84% Container Column (÷) Icon Text Text Row (㲗) Icon Text

Slide 41

Slide 41 text

class TotalPosts extends StatelessWidget { @override Widget build(BuildContext context) { return Container( decoration: ShapeDecoration(shape: RoundedRectangleBorder()), child: Column(children: [ Icon(Icons.photo_album), Text('260'), Text('Total posts'), Row(children: [ Icon(Icons.trending_up), Text('26.84%') ]), ]), ); } }

Slide 42

Slide 42 text

class TotalPosts extends StatelessWidget { @override Widget build(BuildContext context) { return Container( decoration: ShapeDecoration(shape: RoundedRectangleBorder()), child: Column(children: [ Icon(Icons.photo_album), Text('260'), Text('Total posts'), Row(children: [ Icon(Icons.trending_up), Text('26.84%') ]), ]), ); } }

Slide 43

Slide 43 text

Et la gestion de l'état ?

Slide 44

Slide 44 text

No content

Slide 45

Slide 45 text

Les Widgets en Flutter Devfest Lille 2019 Gérer l'état d'un Widget Un Widget est immutable On va lui associer un objet State On utilise un StatefulWidget Il faut appeler la méthode setState pour indiquer que l'état a changé et qu'il faut redessiner

Slide 46

Slide 46 text

class TotalPosts extends StatelessWidget { @override Widget build(BuildContext context) { return Container( decoration: ShapeDecoration(shape: RoundedRectangleBorder()), child: Column(children: [ Icon(Icons.photo_album), Text('260'), Text('Total posts'), Row(children: [ Icon(Icons.trending_up), Text('26.84%') ]), ]), ); } }

Slide 47

Slide 47 text

class TotalPosts extends StatefulWidget { @override _TotalPostsState createState() => _TotalPostsState(); }

Slide 48

Slide 48 text

class _TotalPostsState extends State { int posts = 260; @override Widget build(BuildContext context) { return Container( decoration: ShapeDecoration(shape: RoundedRectangleBorder()), child: Column(children: [ Icon(Icons.photo_album), Text('260'), Text('Total posts'), Row(children: [ Icon(Icons.trending_up), Text('26.84%') ]), ]), ); } }

Slide 49

Slide 49 text

class _TotalPostsState extends State { int posts = 260; @override Widget build(BuildContext context) { return Container( decoration: ShapeDecoration(shape: RoundedRectangleBorder()), child: Column(children: [ Icon(Icons.photo_album), Text('260'), Text('Total posts'), Row(children: [ Icon(Icons.trending_up), Text('26.84%') ]), ]), ); } }

Slide 50

Slide 50 text

class _TotalPostsState extends State { int posts = 260; @override Widget build(BuildContext context) { return Container( decoration: ShapeDecoration(shape: RoundedRectangleBorder()), child: Column(children: [ Icon(Icons.photo_album), Text(posts.toString()), Text('Total posts'), Row(children: [ Icon(Icons.trending_up), Text('26.84%') ]), ]), ); } }

Slide 51

Slide 51 text

class _TotalPostsState extends State { int posts = 260; @override Widget build(BuildContext context) { return InkWell( onTap: () { setState(() { posts++; }); }, child: Container( child: Column(children: [ // Même contenu ]) ), ); } }

Slide 52

Slide 52 text

class _TotalPostsState extends State { int posts = 260; @override Widget build(BuildContext context) { return InkWell( onTap: () { setState(() { posts++; }); }, child: Container( child: Column(children: [ // Même contenu ]) ), ); } }

Slide 53

Slide 53 text

Oui, mais…

Slide 54

Slide 54 text

Les Widgets en Flutter Devfest Lille 2019 Les Widgets ont aussi quelques particularités… Une instance est immutable L'arbre est aussi immutable Ne connaît pas sa taille Ne connaît pas sa position à l'écran Ne connaît pas ses voisins Ne sait pas dessiner à l'écran

Slide 55

Slide 55 text

La notion d'Element

Slide 56

Slide 56 text

Un widget décrit la configuration d'un Element “ “

Slide 57

Slide 57 text

Les Widgets en Flutter Devfest Lille 2019 La création du couple Widget/Element 1 Instancier le Widget 2 Créer un Element 3 Associer les deux 4 Et on fait cela pour tous les Widget(s) Widget Element Widget Element Widget Element Arbre des widgets Arbre des éléments

Slide 58

Slide 58 text

Un Element désigne l'instanciation d'un Widget à un endroit de l'arbre “ “

Slide 59

Slide 59 text

Widget A Widget B Widget D Widget E Widget C Widget F Widget G

Slide 60

Slide 60 text

Element A Element B Element D Element E Element C Element F Element G

Slide 61

Slide 61 text

Le BuildContext ?

Slide 62

Slide 62 text

class TotalPosts extends StatelessWidget { @override Widget build(BuildContext context) { return Container( decoration: ShapeDecoration(shape: RoundedRectangleBorder()), child: Column(children: [ Icon(Icons.photo_album), Text('260'), Text('Total posts'), Row(children: [ Icon(Icons.trending_up), Text('26.84%') ]), ]), ); } }

Slide 63

Slide 63 text

Les objets BuildContext sont en réalité des objets de type Element. L'interface BuildContext est utilisée pour éviter la manipulation directe d'un Element. “ “

Slide 64

Slide 64 text

Communication

Slide 65

Slide 65 text

BuildContext A BuildContext B BuildContext C BuildContext D BuildContext E BuildContext F BuildContext G

Slide 66

Slide 66 text

BuildContext A BuildContext B BuildContext C BuildContext D BuildContext E BuildContext F BuildContext G

Slide 67

Slide 67 text

BuildContext A BuildContext B BuildContext C BuildContext D BuildContext E BuildContext F BuildContext G

Slide 68

Slide 68 text

L'Inherited Widget

Slide 69

Slide 69 text

Propage des informations d'un père vers ses enfants “ “

Slide 70

Slide 70 text

Les Widgets en Flutter Devfest Lille 2019 Un exemple de InheritedWidget Thème de l'application La recherche se fait grâce au BuildContext “ “ Le père fournit : Le fils appelle : .accentColor Theme.of(context)

Slide 71

Slide 71 text

class FrogColor extends InheritedWidget { const FrogColor({ Key key, @required this.color, @required Widget child, }) : assert(color != null), assert(child != null), super(key: key, child: child); final Color color; static FrogColor of(BuildContext context) { return context.inheritFromWidgetOfExactType(FrogColor) as FrogColor; } @override bool updateShouldNotify(FrogColor old) => color != old.color; }

Slide 72

Slide 72 text

class FrogColor extends InheritedWidget { const FrogColor({ Key key, @required this.color, @required Widget child, }) : assert(color != null), assert(child != null), super(key: key, child: child); final Color color; static FrogColor of(BuildContext context) { return context.inheritFromWidgetOfExactType(FrogColor) as FrogColor; } @override bool updateShouldNotify(FrogColor old) => color != old.color; }

Slide 73

Slide 73 text

class FrogColor extends InheritedWidget { const FrogColor({ Key key, @required this.color, @required Widget child, }) : assert(color != null), assert(child != null), super(key: key, child: child); final Color color; static FrogColor of(BuildContext context) { return context.inheritFromWidgetOfExactType(FrogColor) as FrogColor; } @override bool updateShouldNotify(FrogColor old) => color != old.color; }

Slide 74

Slide 74 text

A FrogColor B D E C FrogColor F G

Slide 75

Slide 75 text

A FrogColor B D E C FrogColor F G FrogColor.of(context)

Slide 76

Slide 76 text

A FrogColor B D E C FrogColor F G

Slide 77

Slide 77 text

A FrogColor B D E C FrogColor F G

Slide 78

Slide 78 text

A FrogColor B D E C FrogColor F G

Slide 79

Slide 79 text

A FrogColor B D E C FrogColor F G FrogColor.of(context)

Slide 80

Slide 80 text

A FrogColor B D E C FrogColor F G

Slide 81

Slide 81 text

Le changement

Slide 82

Slide 82 text

class FrogColor extends InheritedWidget { const FrogColor({ Key key, @required this.color, @required Widget child, }) : assert(color != null), assert(child != null), super(key: key, child: child); final Color color; static FrogColor of(BuildContext context) { return context.inheritFromWidgetOfExactType(FrogColor) as FrogColor; } @override bool updateShouldNotify(FrogColor old) => color != old.color; }

Slide 83

Slide 83 text

A FrogColor B D E C F G

Slide 84

Slide 84 text

A FrogColor B D E C F G

Slide 85

Slide 85 text

Le rendu

Slide 86

Slide 86 text

Les Widgets en Flutter Devfest Lille 2019 Rappel sur les Widgets… Un Widget est immutable Ne connaît pas sa taille Ne connaît pas sa position à l'écran Ne connaît pas ses voisins Ne sait pas dessiner à l'écran

Slide 87

Slide 87 text

Pour qu'un Widget puisse être dessiné, il faut lui attacher un RenderObject “ “

Slide 88

Slide 88 text

Les Widgets en Flutter Devfest Lille 2019 Un RenderObject a trois rôles Gestion de l'agencement et de la taille (layout) Dessin à l'écran Gestion de l'interaction (hit testing)

Slide 89

Slide 89 text

Les Widgets en Flutter Devfest Lille 2019 Non pas deux, mais trois arbres Arbre des éléments Arbre mutable qui fait le lien entre un Widget et son RenderObject Arbre de widgets Arbre immutable qui décrit les composants et leurs valeurs Arbre de rendu Arbre mutable de RenderObjects qui s'occupe de gérer le layout, le dessin et le touch

Slide 90

Slide 90 text

Arbre des widgets Arbre des éléments Arbre de rendu RenderObjectWidget RenderObjectWidget Theme Element Element RenderObject Element RenderObject

Slide 91

Slide 91 text

Les Widgets en Flutter Devfest Lille 2019 Objectif accompli Décrire/déclarer notre UI Gérer l'état des Widgets Gérer le rendu d'un Widget

Slide 92

Slide 92 text

Oui, mais…

Slide 93

Slide 93 text

Que se passe-t-il lors des mises à jour ? “ “

Slide 94

Slide 94 text

Arbre des widgets Arbre des éléments Evénements 1 On affiche un Widget Text('Hello') Element 2 On modifie le texte pour "Hello world" Element Element Text('Hello World') Element Text('Hello World')

Slide 95

Slide 95 text

Arbre des widgets Arbre des éléments Evénements 1 On affiche un texte "Hello" Text('Hello') Element 2 On remplace par un autre Widget Element Element Image() Image() Element Image()

Slide 96

Slide 96 text

Créer une classe avec const renvoie la même instance “ “ new Text("a") new Text("b") new Text("a") new Text("a") const Text("a") const Text("a") const Text("a") const Text("b")

Slide 97

Slide 97 text

Arbre des widgets Arbre des éléments Evénements 1 On affiche un texte const("Hello") const Text('Hello') Element 2 On modifie le texte pour "Hello world" Element Element const Text('Hello')

Slide 98

Slide 98 text

Les Widgets en Flutter Devfest Lille 2019 Cela peut paraître compliqué… Arbre des éléments Arbre mutable qui fait le lien entre un Widget et son RenderObject Arbre de widgets Arbre qui décrit les composants et leurs valeurs Arbre de rendu Arbre mutable de RenderObjects qui s'occupent de gérer le layout, le dessin et le touch

Slide 99

Slide 99 text

Merci ! Questions ? @g123k @FlutterFr