Loupe

Flutter : ajouter un thème à votre application

Flutter flutter, here we go again... ♪

Vous l'aurez deviné, nous allons encore une fois parler de Flutter dans ce nouvel article. Mais avant cela, un petit résumé pour ceux qui n'aurait pas tout suivi. Jusqu'ici, nous avons :

Aujourd'hui, nous allons donc reprendre cette dernière application et tenter de la rendre un peu plus jolie (je dis bien "tenter", je ne suis que dev).

Que je thème, que je thèèème

La dernière fois, en détaillant le contenu de la classe App, nous avons remarqué qu'un paramètre theme était disponible dans le constructeur de MaterialApp :

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo Login',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Connexion'),
    );
  }
}

C'est ce paramètre que nous allons modifier pour personnaliser notre petite application.

L'app aux yeux menthe à l'eau

Commençons par choisir les couleurs de notre application.

Nous sommes dans une application de type Material, cela implique donc de définir au moins deux couleurs : PrimaryColor et SecondaryColor. La couleur primaire sera celle de votre barre de navigation. La couleur secondaire sera la couleur d'accent, par exemple, la couleur de votre bouton flottant (FloatingActionButton). Une fois ces deux couleurs choisies, il nous faut une déclinaison light et dark de ces couleurs. Vous pouvez les définir vous même, ou bien utiliser cet outil qui les génèrera pour vous. Pour ma part j'ai choisi la couleur #008080 en tant que couleur primaire et #b2dfdb en secondaire (on dirait pas un peu des couleurs menthe à l'eau ?).

01_colors.PNG  02_ex_colors.PNG

Ensuite, créons une classe qui contiendra le thème de notre application dans laquelle nous définirons nos couleurs. Les couleurs sont définies à l'aide de la classe Color qui accepte les couleurs de la forme hexadécimale (avec les 8 digits). Ainsi ma couleur #008080 devient Color(0xFF008080).

import 'package:flutter/material.dart';

const PrimaryColor = const Color(0xFF008080); 
const PrimaryColorLight = const Color(0xFF4cb0af);
const PrimaryColorDark = const Color(0xFF005354);

const SecondaryColor = const Color(0xFFb2dfdb);
const SecondaryColorLight = const Color(0xFFe5ffff);
const SecondaryColorDark = const Color(0xFF82ada9);

const Background = const Color(0xFFfffdf7);
const TextColor = const Color(0xFF004d40);

class MyTheme {
}

Ah qu'elles sont jolies les couleurs de mon appli

Maintenant que vous avons nos jolies couleurs, passons à la définition du thème. Ajoutons donc une propriété defaultTheme qui appelle la méthode de construction du thème :

class MyTheme {
  static final ThemeData defaultTheme = _buildMyTheme();

  static ThemeData _buildTheme() {
  }
}

Dans la méthode _buildTheme, nous allons dupliquer le thème clair (ThemeData.light) et le modifier avec nos nouvelles couleurs. La duplication nous évitera de redéfinir toutes toutes toutes les couleurs.

class MyTheme {
  static final ThemeData defaultTheme = _buildTheme();

  static ThemeData _buildTheme() {
    final ThemeData base = ThemeData.light();

    return base.copyWith(
      accentColor: SecondaryColor,
      accentColorBrightness: Brightness.dark,
      
      primaryColor: PrimaryColor,
      primaryColorDark: PrimaryColorDark,
      primaryColorLight: PrimaryColorLight,
      primaryColorBrightness: Brightness.dark,

      buttonTheme: base.buttonTheme.copyWith(
        buttonColor: SecondaryColor,
        textTheme: ButtonTextTheme.primary,
      ),
      
      scaffoldBackgroundColor: Background,
      cardColor: Background,
      textSelectionColor: PrimaryColorLight,
      backgroundColor: Background,
      
      textTheme: base.textTheme.copyWith(
        title: base.textTheme.title.copyWith(color: TextColor),
        body1: base.textTheme.body1.copyWith(color: TextColor),
        body2: base.textTheme.body2.copyWith(color: TextColor)
      ),
    );
  }
}

And TADA! Voilà notre application légèrement plus jolie avec de jolies couleurs :)

03_theme.jpg

Éteins la lumière, montre-moi ton coté sombre

Maintenant, si vous aussi les applications toutes blanches vous font mal aux yeux, nous allons voir comment définir un thème sombre. Nous pourrions simplement définir des couleurs plus sombres lors de l'étape précédente, ou bien nous pouvons laissez le choix à l'utilisateur d'utiliser l'application claire ou sombre.

Pour cela, le package dynamic_theme existe et simplifie la tache. Voyons donc comment l'utiliser.

Commençons par l'importer en ajoutant la ligne dynamic_theme: ^1.0.1 dans les dependencies se trouvant dans le fichier pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  dynamic_theme: ^1.0.1

Ensuite, de la même manière qu'à l'étape précédente, définissons un nouveau thème avec cette fois des couleurs plus sombres.

const DarkBackground = const Color(0xFF222727);

class MyTheme {
  static final ThemeData darkTheme = _buildDarkTheme();
  ...

  static ThemeData _buildDarkTheme() {
    final ThemeData base = ThemeData.dark();

    return base.copyWith(
      accentColor: SecondaryColor,
      accentColorBrightness: Brightness.dark,
      
      primaryColor: PrimaryColor,
      primaryColorDark: PrimaryColorDark,
      primaryColorLight: PrimaryColorLight,
      primaryColorBrightness: Brightness.dark,

      buttonTheme: base.buttonTheme.copyWith(
        buttonColor: SecondaryColor,
        textTheme: ButtonTextTheme.primary,
      ),
      
      scaffoldBackgroundColor: DarkBackground,
      cardColor: DarkBackground,
      textSelectionColor: PrimaryColorLight,
      backgroundColor: Background,
      
      textTheme: base.textTheme.copyWith(
        title: base.textTheme.title.copyWith(color: TextColor),
        body1: base.textTheme.body1.copyWith(color: TextColor),
        body2: base.textTheme.body2.copyWith(color: TextColor)
      ),
    );
  }

Puis dans la classe MyApp, ajoutons les deux thèmes créés précédements en fonction de la luminosité choisie (brightness) :

import 'package:dynamic_theme/dynamic_theme.dart';

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new DynamicTheme(
      defaultBrightness: Brightness.light,
      data: (brightness) => brightness == Brightness.light
          ? MyTheme.defaultTheme
          : MyTheme.darkTheme,
      themedWidgetBuilder: (context, theme) {
        return MaterialApp(
          title: 'Flutter Demo Login',
          theme: theme,
          home: MyHomePage(title: 'Connexion'),
        );
      },
    );
  }
}

Maintenant, la partie intéressante : il nous faut permettre à l'utilisateur de choisir entre les deux thèmes. Pour cela, nous allons modifier l'AppBar de notre page pour ajouter un bouton permettant de changer le thème.

Ajoutons donc une méthode dans la classe _MyHomePageState qui modifie la luminosité de l'application (brightness) afin de modifier le thème de l'application.

void _turnOnOffLight() {
DynamicTheme.of(context).setBrightness(
    Theme.of(context).brightness == Brightness.dark
        ? Brightness.light
        : Brightness.dark);
}

Et finalement, ajoutons l'action dans la barre de navigation qui appellera cette méthode.

appBar: AppBar(
    title: Text(widget.title),
    actions: <Widget>[
        IconButton(onPressed: _turnOnOffLight, icon: Icon(Icons.lightbulb_outline))
    ],
),

And TADA! Voila notre application sombre (non Jonathan, pas comme le Titanic) !

04_dark.jpg

I feel pretty, oh so pretty

Et voila la comparaison. Finalement je ne suis pas sure que ce soit plus joli mais au moins nous avons pu investiguer les thèmes en Flutter.

06_compare.png     05_theme_switch.jpg

Et pour le code source : le repo a été mis à jour et c'est par ici !

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus