CHAPITRE 3.1

Afficher du contenu visuel

Personnalisez l'apparence de votre texte pour créer des interfaces attrayantes
Jusqu'à présent, vous avez utilisé le widget Text() pour afficher du texte simple. Dans ce chapitre, nous allons découvrir comment personnaliser l'apparence de ce texte : changer sa taille, sa couleur, son style, son alignement, et gérer les cas où le texte est trop long. Chaque propriété sera introduite progressivement, avec du code minimal et clair.

3.1Afficher du contenu visuel

3.1.1 – Mise en forme du texte avec Text

Le widget Text() que vous avez utilisé jusqu'à présent affiche du texte avec un style par défaut. Mais vous pouvez personnaliser complètement l'apparence de ce texte en utilisant le paramètre style.

🎨 Taille, couleur et style

Pour personnaliser le texte, nous utilisons le paramètre style qui contient un objet TextStyle. Commençons par les propriétés les plus simples :

Text(
  'Bonjour Flutter !',
  style: TextStyle(
    fontSize: 24,
    color: Colors.blue,
  ),
)

Analysons ce code :

  • 'Bonjour Flutter !' : Le texte à afficher (comme avant)
  • style: TextStyle( : Nous définissons un style personnalisé
  • fontSize: 24 : La taille du texte (24 pixels)
  • color: Colors.blue : La couleur du texte (bleu)
TextStyle est une classe qui permet de définir tous les aspects visuels d'un texte : taille, couleur, style (gras, italique), etc. C'est comme choisir la police, la taille et la couleur dans un traitement de texte.
fontSize définit la taille du texte en pixels. Plus le nombre est grand, plus le texte est gros. Par exemple :
  • fontSize: 12 : texte très petit
  • fontSize: 16 : texte normal (taille par défaut)
  • fontSize: 24 : texte grand
  • fontSize: 32 : texte très grand

🧪 Exemple complet : texte personnalisé

Voici un exemple complet dans une application :

Exemple visuel d'un texte personnalisé avec Text
Exemple visuel : un texte personnalisé avec TextStyle.
import 'package:flutter/material.dart';

void main() {
  runApp(const MaPage());
}

class MaPage extends StatelessWidget {
  const MaPage({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Mon Application'),
        ),
        body: SafeArea(
          child: Center(
            child: Text(
              'Bonjour Flutter !',
              style: TextStyle(
                fontSize: 24,
                color: Colors.blue,
              ),
            ),
          ),
        ),
      ),
    );
  }
}

Dans ce code, le texte "Bonjour Flutter !" s'affichera en bleu avec une taille de 24 pixels, centré à l'écran.

Expérimenter :
Essayez de modifier les valeurs :
  • Changez fontSize: 24 en fontSize: 40 pour un texte plus grand
  • Changez color: Colors.blue en color: Colors.red pour un texte rouge
  • Essayez d'autres couleurs : Colors.green, Colors.orange, Colors.purple

📝 Ajouter le style gras et italique

Vous pouvez aussi rendre le texte gras ou italique :

Text(
  'Texte en gras',
  style: TextStyle(
    fontSize: 24,
    color: Colors.blue,
    fontWeight: FontWeight.bold,
  ),
)

Pour le texte en italique :

Text(
  'Texte en italique',
  style: TextStyle(
    fontSize: 24,
    color: Colors.blue,
    fontStyle: FontStyle.italic,
  ),
)
fontWeight et fontStyle :
  • fontWeight: FontWeight.bold : rend le texte gras
  • fontWeight: FontWeight.normal : texte normal (par défaut)
  • fontStyle: FontStyle.italic : rend le texte italique
  • fontStyle: FontStyle.normal : texte normal (par défaut)
Important :
Vous pouvez combiner plusieurs propriétés dans un même TextStyle. Par exemple, vous pouvez avoir un texte à la fois gras, italique, bleu et de taille 24.

📐 Alignement

Par défaut, le texte s'aligne à gauche. Mais vous pouvez changer l'alignement avec le paramètre textAlign :

Text(
  'Texte centré',
  textAlign: TextAlign.center,
  style: TextStyle(
    fontSize: 24,
    color: Colors.blue,
  ),
)

Les valeurs possibles pour textAlign sont :

  • TextAlign.left : aligné à gauche (par défaut)
  • TextAlign.center : centré
  • TextAlign.right : aligné à droite
  • TextAlign.justify : justifié (répartit le texte sur toute la largeur)
Attention :
Le paramètre textAlign fonctionne uniquement si le texte occupe plusieurs lignes ou si le widget Text a une largeur définie. Si votre texte est dans un Center sans contrainte de largeur, l'alignement peut ne pas être visible.

🧪 Exemple : texte avec alignement

Pour voir l'effet de l'alignement, utilisons un Container avec une largeur définie :

Texte centré dans un Container de 300 pixels de large
Exemple visuel : le texte est centré dans un Container de largeur fixe.
import 'package:flutter/material.dart';

void main() {
  runApp(const MaPage());
}

class MaPage extends StatelessWidget {
  const MaPage({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Mon Application'),
        ),
        body: SafeArea(
          child: Center(
            child: Container(
              width: 300,
              color: Colors.grey[200],
              padding: const EdgeInsets.all(16),
              child: Text(
                'Ce texte est centré dans un Container de 300 pixels de large.',
                textAlign: TextAlign.center,
                style: TextStyle(
                  fontSize: 18,
                  color: Colors.blue,
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

Dans cet exemple, le texte est centré à l'intérieur du Container de 300 pixels de large.

Pourquoi Container ?
Sans Container (ou un autre widget qui définit une largeur), le texte prend toute la largeur disponible et l'alignement n'est pas visible. Le Container avec width: 300 limite la largeur, ce qui permet de voir l'effet du centrage.

⚠️ Gestion du dépassement

Parfois, le texte est trop long pour tenir dans l'espace disponible. Par défaut, Flutter affiche une erreur (overflow). Pour gérer cela, nous utilisons le paramètre overflow :

Exemple visuel d'un texte long coupé par overflow ellipsis
Exemple visuel : un texte trop long coupé avec overflow: TextOverflow.ellipsis.
Text(
  'Ce texte est très très très long et risque de dépasser...',
  overflow: TextOverflow.ellipsis,
  style: TextStyle(
    fontSize: 18,
  ),
)

Les valeurs possibles pour overflow sont :

  • TextOverflow.ellipsis : coupe le texte et ajoute "..." à la fin
  • TextOverflow.clip : coupe le texte sans ajouter de "..."
  • TextOverflow.fade : fait disparaître progressivement le texte à la fin
  • TextOverflow.visible : affiche le texte même s'il dépasse (peut causer des erreurs)
TextOverflow.ellipsis :
C'est la solution la plus courante. Si le texte est trop long, Flutter le coupe et ajoute trois points (...) à la fin. C'est ce que vous voyez souvent dans les applications : "Ce texte est très long..." au lieu de "Ce texte est très très très long et dépasse".

🧪 Exemple : gestion du dépassement

Voici un exemple complet avec gestion du dépassement :

import 'package:flutter/material.dart';

void main() {
  runApp(const MaPage());
}

class MaPage extends StatelessWidget {
  const MaPage({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Mon Application'),
        ),
        body: SafeArea(
          child: Center(
            child: Container(
              width: 200,
              color: Colors.grey[200],
              padding: const EdgeInsets.all(16),
              child: Text(
                'Ce texte est très très très long et risque de dépasser de la largeur du Container.',
                overflow: TextOverflow.ellipsis,
                style: TextStyle(
                  fontSize: 18,
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

Dans cet exemple, le texte est limité à 200 pixels de large. Si le texte est trop long, il sera coupé et se terminera par "...".

Important :
Pour que overflow fonctionne, le texte doit avoir une contrainte de largeur (comme un Container avec width). Sinon, le texte prend toute la largeur disponible et ne dépassera jamais.

💡 Points clés à retenir

  • Le paramètre style avec TextStyle permet de personnaliser l'apparence du texte
  • fontSize définit la taille du texte en pixels
  • color définit la couleur du texte
  • fontWeight: FontWeight.bold rend le texte gras
  • fontStyle: FontStyle.italic rend le texte italique
  • textAlign permet d'aligner le texte (left, center, right, justify)
  • overflow permet de gérer les textes trop longs (ellipsis, clip, fade, visible)
Résumé de la structure :
Voici la structure complète d'un Text() avec toutes les options que nous avons vues :
Text(
  'Votre texte ici',
  textAlign: TextAlign.center,
  overflow: TextOverflow.ellipsis,
  style: TextStyle(
    fontSize: 24,
    color: Colors.blue,
    fontWeight: FontWeight.bold,
    fontStyle: FontStyle.italic,
  ),
)
Vous pouvez utiliser toutes ces propriétés ensemble ou séparément, selon vos besoins.
Prochaine étape :
Maintenant que vous savez personnaliser le texte, nous allons découvrir les icônes, qui permettent d'ajouter des symboles visuels à votre interface.

3.1.2 – Utiliser les icônes avec Icon

Les icônes sont des symboles visuels simples qui permettent d'améliorer l'interface de votre application. Flutter fournit une grande collection d'icônes prédéfinies grâce à Material Design. Le widget Icon permet de les afficher facilement.

🎨 Icônes Material

Flutter inclut des milliers d'icônes Material Design prêtes à l'emploi. Ces icônes sont accessibles via la classe Icons. Voici comment utiliser une icône :

Icon(Icons.star)

C'est tout ! Icon(Icons.star) affiche une icône d'étoile. La syntaxe est très simple :

  • Icon( : Le widget qui affiche une icône
  • Icons.star : L'icône à afficher (une étoile)
Icons :
Icons est une classe qui contient toutes les icônes Material Design disponibles. Il y en a des centaines ! Par exemple :
  • Icons.star : une étoile
  • Icons.home : une maison
  • Icons.favorite : un cœur
  • Icons.settings : une roue dentée
  • Icons.search : une loupe
  • Icons.add : un signe plus
Comment trouver les icônes disponibles ?
Dans votre éditeur (VS Code ou Android Studio), tapez Icons. et vous verrez une liste de toutes les icônes disponibles avec leur aperçu. Vous pouvez aussi consulter la documentation officielle des icônes Material.
Aperçu de la Google Material Icon Gallery
Capture d'écran : aperçu de la galerie officielle des icônes Material.

📏 Taille et couleur

Par défaut, l'icône a une taille et une couleur standard. Mais vous pouvez les personnaliser avec les paramètres size et color :

Icon(
  Icons.star,
  size: 48,
  color: Colors.amber,
)

Analysons ce code :

  • Icons.star : L'icône à afficher (étoile)
  • size: 48 : La taille de l'icône (48 pixels)
  • color: Colors.amber : La couleur de l'icône (ambre/doré)
size :
size définit la taille de l'icône en pixels. Plus le nombre est grand, plus l'icône est grande. Par défaut, la taille est de 24 pixels. Par exemple :
  • size: 16 : icône très petite
  • size: 24 : icône normale (par défaut)
  • size: 48 : icône grande
  • size: 64 : icône très grande
color :
color définit la couleur de l'icône. Vous pouvez utiliser n'importe quelle couleur de Colors, comme pour le texte. Par exemple : Colors.blue, Colors.red, Colors.green, etc.

🧪 Exemple complet : icône personnalisée

Voici un exemple complet dans une application :

Exemple d'icône personnalisée avec Icon
Exemple visuel : une grande étoile dorée affichée avec le widget Icon.
import 'package:flutter/material.dart';

void main() {
  runApp(const MaPage());
}

class MaPage extends StatelessWidget {
  const MaPage({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Mon Application'),
        ),
        body: SafeArea(
          child: Center(
            child: Icon(
              Icons.star,
              size: 64,
              color: Colors.amber,
            ),
          ),
        ),
      ),
    );
  }
}

Dans ce code, une grande étoile dorée s'affichera au centre de l'écran.

Expérimenter :
Essayez de modifier les valeurs :
  • Changez Icons.star en Icons.favorite pour un cœur
  • Changez size: 64 en size: 100 pour une icône encore plus grande
  • Changez color: Colors.amber en color: Colors.red pour une icône rouge
  • Essayez d'autres icônes : Icons.home, Icons.settings, Icons.search

🔗 Intégration

Les icônes sont souvent utilisées avec d'autres widgets. Par exemple, vous pouvez combiner une icône avec du texte dans une Column :

Column(
  children: [
    Icon(
      Icons.star,
      size: 48,
      color: Colors.amber,
    ),
    Text('Favoris'),
  ],
)

Dans cet exemple, l'icône d'étoile est affichée au-dessus du texte "Favoris". Ils sont organisés verticalement grâce à Column.

🧪 Exemple : icône avec texte

Voici un exemple complet avec une icône et du texte :

Icône avec texte sous l'icône dans une colonne
Exemple visuel : une icône affichée au-dessus du texte dans une Column.
import 'package:flutter/material.dart';

void main() {
  runApp(const MaPage());
}

class MaPage extends StatelessWidget {
  const MaPage({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Mon Application'),
        ),
        body: SafeArea(
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Icon(
                  Icons.favorite,
                  size: 64,
                  color: Colors.red,
                ),
                const SizedBox(height: 16),
                const Text(
                  'Mes favoris',
                  style: TextStyle(
                    fontSize: 24,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Dans cet exemple, une grande icône de cœur rouge est affichée au-dessus du texte "Mes favoris", le tout centré à l'écran.

SizedBox(height: 16) :
SizedBox(height: 16) ajoute un espace vertical de 16 pixels entre l'icône et le texte. C'est un widget simple qui permet d'ajouter de l'espacement. Nous l'utilisons ici pour séparer visuellement l'icône du texte.
mainAxisAlignment: MainAxisAlignment.center :
Ce paramètre de Column centre les éléments verticalement. Nous l'avons déjà vu dans le chapitre 2.4. Il permet de centrer l'icône et le texte au milieu de l'écran.

💡 Points clés à retenir

  • Le widget Icon() affiche une icône Material Design
  • Icons contient toutes les icônes disponibles (Icons.star, Icons.home, Icons.favorite, etc.)
  • size définit la taille de l'icône en pixels (par défaut : 24)
  • color définit la couleur de l'icône (comme pour le texte)
  • Les icônes peuvent être combinées avec d'autres widgets (Text, Column, etc.)
Résumé de la structure :
Voici la structure complète d'un Icon() avec toutes les options :
Icon(
  Icons.nom_de_l_icone,
  size: 48,
  color: Colors.blue,
)
Vous pouvez utiliser toutes ces propriétés ensemble ou séparément, selon vos besoins.
Prochaine étape :
Maintenant que vous savez utiliser les icônes, découvrons comment afficher des images dans votre application.

3.1.3 – Afficher des images

Les images sont essentielles pour créer des interfaces attrayantes. Flutter permet d'afficher des images de deux manières : depuis votre projet (images locales) ou depuis Internet (images réseau). Découvrons comment faire.

📁 Images locales

Les images locales sont des fichiers image que vous placez dans votre projet Flutter. Pour les utiliser, vous devez d'abord les ajouter au projet, puis les référencer dans votre code.

Où placer les images ?
Dans un projet Flutter, les images se placent généralement dans un dossier assets/images/ à la racine du projet. Vous devez ensuite déclarer ces images dans le fichier pubspec.yaml de votre projet.

Pour afficher une image locale, utilisez le widget Image.asset() :

Image.asset('assets/images/mon_image.png')

Analysons ce code :

  • Image.asset( : Le widget qui affiche une image locale
  • 'assets/images/mon_image.png' : Le chemin vers l'image dans votre projet
Important :
Pour que Image.asset() fonctionne, vous devez :
  1. Créer le dossier assets/images/ (s'il n'existe pas déjà), puis y placer l'image de votre choix
  2. Déclarer le dossier dans le fichier pubspec.yaml :
    flutter:
      assets:
        - assets/images/
  3. Attention : l'indentation (les espaces) est très importante dans le fichier pubspec.yaml. Chaque ligne enfant doit être indentée avec 2 espaces (pas de tabulations), y compris les lignes commençant par un tiret (-). Une mauvaise indentation peut empêcher votre projet de fonctionner.
  4. Redémarrer l'application après avoir modifié pubspec.yaml
Exemple d'utilisation de Image.asset dans Flutter
Exemple visuel : afficher une image locale dans Flutter avec Image.asset

🌐 Images réseau

Les images réseau sont des images hébergées sur Internet. Pour les afficher, utilisez le widget Image.network() :

Image.network('https://example.com/image.jpg')

Analysons ce code :

  • Image.network( : Le widget qui affiche une image depuis Internet
  • 'https://example.com/image.jpg' : L'URL (adresse) de l'image sur Internet
URL :
Une URL (Uniform Resource Locator) est l'adresse d'une ressource sur Internet. Pour une image, c'est l'adresse complète qui commence par https:// ou http://.
Attention :
Pour que Image.network() fonctionne, votre appareil ou simulateur doit avoir une connexion Internet. Si l'image n'est pas accessible ou si l'URL est incorrecte, vous verrez une erreur.

🧪 Exemple complet : image réseau

Voici un exemple complet avec une image réseau :

Exemple d'utilisation de Image.network dans Flutter
Exemple visuel : afficher une image réseau dans Flutter avec Image.network
import 'package:flutter/material.dart';

void main() {
  runApp(const MaPage());
}

class MaPage extends StatelessWidget {
  const MaPage({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Mon Application'),
        ),
        body: SafeArea(
          child: Center(
            child: Image.network(
              'http://mazoul.online/images/courses/flutter/chapitre_3/owl.jpg',
              width: 300,
              height: 300,
              fit: BoxFit.cover,
            ),
          ),
        ),
      ),
    );
  }
}

Dans cet exemple, une image de 300x300 pixels est affichée au centre de l'écran. L'URL http://mazoul.online/images/courses/flutter/chapitre_3/owl.jpg pointe vers une image de démonstration officielle proposée par Flutter.

width et height :
Les paramètres width et height définissent la taille de l'image affichée. Sans ces paramètres, l'image prendra sa taille naturelle, ce qui peut être trop grand ou trop petit.

📐 BoxFit

Par défaut, une image peut être déformée si sa taille ne correspond pas à l'espace disponible. Le paramètre fit permet de contrôler comment l'image s'adapte à son espace :

Image.network(
  'https://example.com/image.jpg',
  width: 200,
  height: 200,
  fit: BoxFit.cover,
)

Les valeurs possibles pour BoxFit sont :

  • BoxFit.cover : L'image remplit tout l'espace en gardant ses proportions. Elle peut être coupée si nécessaire.
  • BoxFit.contain : L'image s'adapte entièrement dans l'espace en gardant ses proportions. Il peut y avoir des espaces vides.
  • BoxFit.fill : L'image remplit tout l'espace, mais peut être déformée.
  • BoxFit.fitWidth : L'image s'adapte à la largeur disponible.
  • BoxFit.fitHeight : L'image s'adapte à la hauteur disponible.
BoxFit.cover vs BoxFit.contain :
  • BoxFit.cover : L'image remplit tout l'espace, mais peut être coupée. C'est comme une photo de couverture qui remplit tout l'écran.
  • BoxFit.contain : L'image entière est visible, mais il peut y avoir des espaces vides. C'est comme une photo dans un cadre qui montre toute l'image.
En général, BoxFit.cover est utilisé pour les images de fond, et BoxFit.contain pour les images de contenu.

🧪 Exemple complet : BoxFit

Voici un exemple qui montre la différence entre BoxFit.cover et BoxFit.contain :

Comparaison visuelle entre BoxFit.cover et BoxFit.contain
Exemple visuel : en haut, l'image avec BoxFit.cover (elle remplit tout, mais elle peut être coupée) ; en bas, l'image avec BoxFit.contain (elle garde toute l'image visible, mais il y a de l'espace sur les côtés).
import 'package:flutter/material.dart';

void main() {
  runApp(const MaPage());
}

class MaPage extends StatelessWidget {
  const MaPage({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Mon Application'),
        ),
        body: SafeArea(
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Image.network(
                  'http://mazoul.online/images/courses/flutter/chapitre_3/owl.jpg',
                  width: 200,
                  height: 200,
                  fit: BoxFit.cover,
                ),
                const SizedBox(height: 20),
                const Text('BoxFit.cover'),
                const SizedBox(height: 30),
                Image.network(
                  'http://mazoul.online/images/courses/flutter/chapitre_3/owl.jpg',
                  width: 200,
                  height: 200,
                  fit: BoxFit.contain,
                ),
                const SizedBox(height: 20),
                const Text('BoxFit.contain'),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Dans cet exemple, deux images identiques sont affichées avec des modes BoxFit différents. Vous pouvez voir la différence : cover remplit tout l'espace (peut couper), tandis que contain montre toute l'image (peut laisser des espaces).

👤 CircleAvatar

CircleAvatar est un widget spécial qui affiche une image (ou un texte) dans un cercle. C'est très utile pour afficher des photos de profil, des avatars, etc.

Analogie :
CircleAvatar est comme une photo de profil ronde que vous voyez dans les applications de réseaux sociaux. L'image est automatiquement coupée en cercle.

Voici comment utiliser CircleAvatar avec une image :

CircleAvatar(
  radius: 50,
  backgroundImage: NetworkImage('https://example.com/avatar.jpg'),
)

Analysons ce code :

  • CircleAvatar( : Le widget qui affiche une image circulaire
  • radius: 50 : Le rayon du cercle (50 pixels, donc un diamètre de 100 pixels)
  • backgroundImage: NetworkImage(...) : L'image à afficher (depuis Internet)
NetworkImage vs AssetImage :
  • NetworkImage('url') : Pour les images depuis Internet
  • AssetImage('assets/images/image.png') : Pour les images locales
CircleAvatar utilise backgroundImage qui attend un objet ImageProvider, c'est pourquoi on utilise NetworkImage ou AssetImage au lieu de Image.network().

🧪 Exemple complet : CircleAvatar

Voici un exemple complet avec CircleAvatar :

Exemple CircleAvatar Flutter
Exemple visuel : une image affichée dans un cercle grâce à CircleAvatar.
import 'package:flutter/material.dart';

void main() {
  runApp(const MaPage());
}

class MaPage extends StatelessWidget {
  const MaPage({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Mon Application'),
        ),
        body: SafeArea(
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                CircleAvatar(
                  radius: 100,
                  backgroundImage: NetworkImage('http://mazoul.online/images/courses/flutter/chapitre_3/owl.jpg'),
                ),
                const SizedBox(height: 20),
                const Text(
                  'Photo de profil',
                  style: TextStyle(fontSize: 20),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Dans cet exemple, une image circulaire de 120 pixels de diamètre (radius: 60) est affichée au centre de l'écran, avec un texte en dessous.

Exemple CircleAvatar avec texte
Exemple visuel : CircleAvatar qui affiche des initiales dans un cercle coloré.
CircleAvatar avec texte :
Si vous ne fournissez pas d'image, CircleAvatar peut afficher du texte ou une couleur de fond :
CircleAvatar(
  radius: 50,
  backgroundColor: Colors.blue[700],
  child: Text('MA', style: TextStyle(fontSize: 40, color: Colors.white)),
),
Cela affichera un cercle bleu avec les lettres "MA" au centre.

💡 Points clés à retenir

  • Image.asset() affiche une image locale (depuis votre projet)
  • Image.network() affiche une image depuis Internet
  • width et height définissent la taille de l'image
  • fit: BoxFit.cover remplit l'espace en gardant les proportions (peut couper)
  • fit: BoxFit.contain montre toute l'image en gardant les proportions (peut laisser des espaces)
  • CircleAvatar affiche une image (ou texte) dans un cercle
  • CircleAvatar utilise NetworkImage ou AssetImage pour les images
Résumé des structures :
Voici les structures principales :
// Image locale
Image.asset('assets/images/image.png')

// Image réseau
Image.network('https://example.com/image.jpg', width: 200, height: 200)

// Image avec BoxFit
Image.network('url', width: 200, height: 200, fit: BoxFit.cover)

// CircleAvatar
CircleAvatar(
  radius: 50,
  backgroundImage: NetworkImage('url'),
)
Prochaine étape :
Maintenant que vous savez afficher des images, découvrons comment utiliser des polices personnalisées pour personnaliser encore plus votre interface.

3.1.4 – Utiliser des polices personnalisées

Par défaut, Flutter utilise des polices système. Mais vous pouvez utiliser vos propres polices pour donner une identité visuelle unique à votre application. Pour cela, vous devez ajouter les fichiers de police à votre projet, les déclarer, puis les utiliser.

📁 Ajout des polices

Pour utiliser une police personnalisée, vous devez d'abord avoir le fichier de police (généralement un fichier .ttf ou .otf). Ensuite, vous devez le placer dans votre projet.

Où placer les polices ?
Dans un projet Flutter, les polices se placent généralement dans un dossier assets/fonts/ à la racine du projet. Vous pouvez créer ce dossier s'il n'existe pas déjà.

Structure recommandée :

mon_projet_flutter/
  ├── lib/
  │   └── main.dart
  ├── assets/
  │   └── fonts/
  │       ├── MaPolice-Regular.ttf
  │       └── MaPolice-Bold.ttf
  └── pubspec.yaml
Formats de police :
Flutter supporte les formats de police suivants :
  • .ttf (TrueType Font) : le plus courant
  • .otf (OpenType Font) : aussi très courant
Vous pouvez télécharger des polices gratuites sur des sites comme Google Fonts.
Conseil :
Si vous utilisez Google Fonts, vous pouvez aussi utiliser le package google_fonts qui simplifie beaucoup l'utilisation des polices Google. Mais pour apprendre les bases, nous allons voir comment ajouter manuellement une police.

📝 Déclaration

Une fois la police placée dans le dossier assets/fonts/, vous devez la déclarer dans le fichier pubspec.yaml de votre projet.

Important :
L'indentation (les espaces) est très importante dans le fichier pubspec.yaml. Chaque ligne enfant doit être indentée avec 2 espaces (pas de tabulations). Une mauvaise indentation peut empêcher votre projet de fonctionner.

Voici comment déclarer une police dans pubspec.yaml :

flutter:
  fonts:
    - family: MaPolice
      fonts:
        - asset: assets/fonts/MaPolice-Regular.ttf
        - asset: assets/fonts/MaPolice-Bold.ttf
          weight: 700

Analysons ce code :

  • fonts: : Section pour déclarer les polices
  • - family: MaPolice : Le nom de la famille de police (vous choisissez ce nom)
  • fonts: : Liste des fichiers de police pour cette famille
  • - asset: assets/fonts/MaPolice-Regular.ttf : Chemin vers le fichier de police normal
  • - asset: assets/fonts/MaPolice-Bold.ttf : Chemin vers le fichier de police gras
  • weight: 700 : Le poids (épaisseur) de la police. 400 = normal, 700 = gras
weight (poids) :
Le poids d'une police définit son épaisseur. Les valeurs courantes sont :
  • 100 : très fin (Thin)
  • 300 : fin (Light)
  • 400 : normal (Regular) - c'est la valeur par défaut
  • 500 : moyen (Medium)
  • 700 : gras (Bold)
  • 900 : très gras (Black)
Après modification de pubspec.yaml :
Après avoir modifié le fichier pubspec.yaml, vous devez :
  1. Arrêter complètement l'application (pas juste Hot Reload)
  2. Redémarrer l'application
Flutter doit recharger la configuration pour prendre en compte les nouvelles polices.

🎨 Application

Une fois la police déclarée dans pubspec.yaml et l'application redémarrée, vous pouvez l'utiliser dans votre code avec TextStyle :

Text(
  'Mon texte avec police personnalisée',
  style: TextStyle(
    fontFamily: 'MaPolice',
    fontSize: 24,
  ),
)

Analysons ce code :

  • fontFamily: 'MaPolice' : Le nom de la famille de police que vous avez déclarée dans pubspec.yaml
  • fontSize: 24 : La taille du texte (comme d'habitude)
fontFamily :
Le paramètre fontFamily doit correspondre exactement au nom que vous avez donné dans pubspec.yaml (dans family: MaPolice). C'est sensible à la casse : 'MaPolice' est différent de 'mapolice'.

🧪 Exemple complet : police personnalisée

Voici un exemple complet avec une police personnalisée :

Exemple texte avec police personnalisée
Exemple visuel : du texte avec une police personnalisée en Flutter.
import 'package:flutter/material.dart';

void main() {
  runApp(const MaPage());
}

class MaPage extends StatelessWidget {
  const MaPage({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Mon Application'),
        ),
        body: SafeArea(
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  'Texte sans police',
                  style: TextStyle(
                    fontSize: 24,
                  ),
                ),
                const SizedBox(height: 20),
                Text(
                  'Texte normal',
                  style: TextStyle(
                    fontFamily: 'Pacifico',
                    fontSize: 24,
                  ),
                ),
                const SizedBox(height: 20),
                Text(
                  'Texte en gras',
                  style: TextStyle(
                    fontFamily: 'Pacifico',
                    fontSize: 24,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Dans cet exemple, deux textes utilisent la police personnalisée "Pacifico" : un en style normal, et un en gras.
Télécharger le fichier Pacifico-Regular.ttf

Déclaration de la police dans pubspec.yaml

flutter:
  fonts:
    - family: Pacifico
      fonts:
        - asset: assets/fonts/Pacifico-Regular.ttf

Ce bloc montre comment déclarer la police Pacifico dans votre fichier pubspec.yaml :

  • family: Pacifico : nom que vous utiliserez dans fontFamily.
  • asset: : chemin d'accès au fichier de police dans votre dossier assets/fonts/.
  • weight: 700 : spécifie la version "gras" de la police.
Après avoir ajouté cette configuration et placé les fichiers dans le dossier assets/fonts/, exécutez un flutter pub get, puis redémarrez l’application.
Pour n’avoir que la version régulière, déclarez seulement Pacifico-Regular.ttf sans le paramètre weight.

fontWeight avec police personnalisée :
Quand vous utilisez fontWeight: FontWeight.bold avec une police personnalisée, Flutter recherche automatiquement le fichier de police correspondant au poids demandé. Si vous avez déclaré weight: 700 dans votre configuration pour le fichier gras, Flutter l'utilisera lorsque vous demandez FontWeight.bold.

📋 Exemple : une seule police

Si vous n'avez qu'un seul fichier de police (par exemple, juste la version normale), voici comment le déclarer :

flutter:
  fonts:
    - family: MaPolice
      fonts:
        - asset: assets/fonts/MaPolice-Regular.ttf

Dans ce cas, vous pouvez toujours utiliser fontWeight: FontWeight.bold, mais Flutter simulera le gras (il ne sera pas aussi net qu'avec un vrai fichier de police gras).

💡 Points clés à retenir

  • Les polices personnalisées se placent dans assets/fonts/
  • Les polices doivent être déclarées dans pubspec.yaml sous la section flutter: fonts:
  • Le nom de la famille (family) est celui que vous choisissez
  • Le paramètre weight définit l'épaisseur (400 = normal, 700 = gras)
  • Après modification de pubspec.yaml, il faut redémarrer l'application
  • Utilisez fontFamily: 'NomDeLaPolice' dans TextStyle pour appliquer la police
  • Le nom dans fontFamily doit correspondre exactement au nom dans pubspec.yaml
Résumé de la structure :
Voici le processus complet :
  1. Ajout : Placer le fichier .ttf ou .otf dans assets/fonts/
  2. Déclaration : Ajouter la configuration dans pubspec.yaml
  3. Redémarrage : Redémarrer l'application
  4. Application : Utiliser fontFamily: 'NomPolice' dans TextStyle
Exercice pratique :
Maintenant que vous savez personnaliser le texte, les icônes, les images et les polices, mettez vos connaissances en pratique avec l'exercice ci-dessous !

🎯 Exercice pratique

Objectif : Reproduire l'interface de profil ci-dessous en utilisant tous les concepts appris dans ce chapitre.

Interface de profil à reproduire
Interface à reproduire : Créez cette interface de profil en utilisant les widgets et techniques appris jusqu'à ici.