Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Les Widgets en Flutter

Les Widgets en Flutter

Edouard Marquez

June 14, 2019
Tweet

More Decks by Edouard Marquez

Other Decks in Programming

Transcript

  1. Les Widgets en Flutter
    Edouard Marquez

    (Développeur freelance Flutter & Android)

    View Slide

  2. Avant de commencer

    View Slide

  3. 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*


    View Slide

  4. View Slide

  5. 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

    View Slide

  6. 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++)

    View Slide

  7. 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

    View Slide

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

    View Slide

  9. Les Widgets

    View Slide

  10. 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'),
    );
    }
    }

    View Slide

  11. 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'),
    );
    }
    }

    View Slide

  12. Une application est un Widget


    View Slide

  13. 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'),
    );
    }
    }

    View Slide

  14. 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'),
    );
    }
    }

    View Slide

  15. Qui elle même
    affiche des Widgets ?


    View Slide

  16. Oui, en Flutter
    Tout est un Widget


    View Slide

  17. Les Widgets expliqués

    View Slide

  18. Ceci n'est pas une

    présentation sponsorisée

    View Slide

  19. 1 Il en existe de toutes les formes

    View Slide

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

    View Slide

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

    View Slide

  22. 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

    View Slide

  23. 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

    View Slide

  24. 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

    View Slide

  25. 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

    View Slide

  26. Et appliqué à Flutter ?

    View Slide

  27. 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

    View Slide

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

    Widgets catalog

    View Slide

  29. 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

    View Slide

  30. 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é

    View Slide

  31. 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 !

    View Slide

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

    View Slide

  33. 6 On peut obtenir des résultats complexes

    View Slide

  34. 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 !

    View Slide

  35. Si on résume

    View Slide

  36. 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

    View Slide

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

    View Slide

  38. Mise en application

    View Slide

  39. 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%

    View Slide

  40. 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

    View Slide

  41. 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%')
    ]),
    ]),
    );
    }
    }

    View Slide

  42. 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%')
    ]),
    ]),
    );
    }
    }

    View Slide

  43. Et la gestion de l'état ?

    View Slide

  44. View Slide

  45. 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

    View Slide

  46. 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%')
    ]),
    ]),
    );
    }
    }

    View Slide

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

    View Slide

  48. 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%')
    ]),
    ]),
    );
    }
    }

    View Slide

  49. 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%')
    ]),
    ]),
    );
    }
    }

    View Slide

  50. 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%')
    ]),
    ]),
    );
    }
    }

    View Slide

  51. 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
    ])
    ),
    );
    }
    }

    View Slide

  52. 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
    ])
    ),
    );
    }
    }

    View Slide

  53. Oui, mais…

    View Slide

  54. 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

    View Slide

  55. La notion d'Element

    View Slide

  56. Un widget décrit la
    configuration
    d'un Element


    View Slide

  57. 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

    View Slide

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


    View Slide

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

    View Slide

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

    View Slide

  61. Le BuildContext ?

    View Slide

  62. 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%')
    ]),
    ]),
    );
    }
    }

    View Slide

  63. 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.


    View Slide

  64. Communication

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  68. L'Inherited Widget

    View Slide

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


    View Slide

  70. 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)

    View Slide

  71. 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;
    }

    View Slide

  72. 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;
    }

    View Slide

  73. 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;
    }

    View Slide

  74. A

    FrogColor
    B
    D E
    C

    FrogColor
    F G

    View Slide

  75. A

    FrogColor
    B
    D E
    C

    FrogColor
    F G
    FrogColor.of(context)

    View Slide

  76. A

    FrogColor
    B
    D E
    C

    FrogColor
    F G

    View Slide

  77. A

    FrogColor
    B
    D E
    C

    FrogColor
    F G

    View Slide

  78. A

    FrogColor
    B
    D E
    C

    FrogColor
    F G

    View Slide

  79. A

    FrogColor
    B
    D E
    C

    FrogColor
    F G
    FrogColor.of(context)

    View Slide

  80. A

    FrogColor
    B
    D E
    C

    FrogColor
    F G

    View Slide

  81. Le changement

    View Slide

  82. 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;
    }

    View Slide

  83. A

    FrogColor
    B
    D E
    C
    F G

    View Slide

  84. A

    FrogColor
    B
    D E
    C
    F G

    View Slide

  85. Le rendu

    View Slide

  86. 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

    View Slide

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


    View Slide

  88. 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)

    View Slide

  89. 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

    View Slide

  90. Arbre des

    widgets
    Arbre des

    éléments
    Arbre de

    rendu
    RenderObjectWidget
    RenderObjectWidget
    Theme
    Element
    Element
    RenderObject
    Element RenderObject

    View Slide

  91. 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

    View Slide

  92. Oui, mais…

    View Slide

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


    View Slide

  94. 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')

    View Slide

  95. 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()

    View Slide

  96. 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")

    View Slide

  97. 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')

    View Slide

  98. 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

    View Slide

  99. Merci !


    Questions ?
    @g123k @FlutterFr

    View Slide