• 12 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 01/10/2024

Gérez le style global de l’application grâce aux thèmes

Pour uniformiser le style d'une application Android avec Jetpack Compose, il faut utiliser le concept de thèmes. En particulier, la dépendanceandroidx.compose.material3:material3offre un ensemble complet de composants et d’outils permettant de styliser une application en accord avec les principes de design de Material 3.

Découvrez le concept de thème dans Material Design

La personnalisation des thèmes au sein de Material Design consiste à uniformiser les couleurs, les formes et les typographies. Material Design adopte une approche fonctionnelle. Il définit sémantiquement l’ensemble de ces éléments en fonction de leur intention et leur rôle dans l’interface. Cette approche facilite la cohérence visuelle et la maintenabilité du style de l'application.

Uniformisez les couleurs

Les couleurs sont par exemple nomméesprimary,secondaryetonPrimary. Cela est préférable à la dénomination basée sur la couleur elle-même, avec des noms descriptifs commeblueSky,lavender,olive.

Palette de couleurs avec différentes catégories de teintes primaires, secondaires, tertiaires et surfaces, incluant des variantes et des états d'erreur.
Illustration des couleurs sémantiques claires d’un thème Material 3

Uniformisez les typographies

Voici quelques exemples pour définir du texte :

  • DisplayLarge,DisplayMedium,DisplaySmall: Pour des titres principaux.

  • HeadlineLarge,HeadlineMedium,HeadlineSmall: Pour des titres de section ou de contenu significatif.

  • TitleLarge,TitleMedium,TitleSmall: Pour des titres de section plus courts ou des éléments de navigation.

  • BodyLarge,BodyMedium,BodySmall: Pour des textes classiques avec un impact visuel plus ou moins fort.

  • LabelLarge,LabelMedium,LabelSmall: Pour des annotations descriptives ou des légendes courtes.

Uniformisez les formes

Afin de maintenir une cohérence visuelle, nous pouvons définir uniformément une forme à chaque élément de l'interface utilisateur, en fonction de son rôle et de son contexte d'utilisation. Voici les noms des différentes formes :

  • None: Aucune forme particulière, pour des bords carrés.

  • Small: Coins légèrement arrondis, pour un look discret.

  • Medium: Coins modérément arrondis, pour une apparence plus douce.

  • Large: Coins fortement arrondis, pour un look plus fluide.

  • ExtraLarge: Coins très arrondis, pour une apparence plus fluide et moderne.

  • Full: Forme complètement arrondie, correspondant à une forme circulaire ou ovale.

Voyons maintenant comment Jetpack Compose applique concrètement la spécification Material 3.

Appliquez Material Design avec Jetpack Compose

Utilisez la fonction composableMaterialTheme

Pour personnaliser globalement ces trois attributs de la thématisation (couleurs, typographies et formes), l'élément central à intégrer est la fonction composableMaterialTheme. Elle présente la signature suivante :

@Composable
fun MaterialTheme(
   colorScheme: ColorScheme = MaterialTheme.colorScheme,
   shapes: Shapes = MaterialTheme.shapes,
   typography: Typography = MaterialTheme.typography,
   content: @Composable () -> Unit
) { /*...*/ }

Comme vous pouvez le voir, les paramètrescolors ,typographyetshapes sont optionnels. En l’absence de personnalisation, chaque paramètre a un style par défaut. Le quatrième paramètre  contentest une lambda de type Composable. C’est ici que l’on positionne le contenu à styliser.

Ainsi, pour styliser tout ou partie d'une application, il suffit de l’englober avec la fonctionMaterialTheme. Cela permet à cette partie d'adopter le thème défini, l’affectant aussi automatiquement à tous ses enfants. Par exemple, pour appliquer un thème à l’ensemble d’une activité, on écrit :

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            MaterialTheme( 
      		colors = /* TODO couleurs à personnaliser*/, 
      		typography =/* TODO typographie à personnaliser*/,        
      		shapes = /* TODO formes à personnaliser*/ 
    		) { 
        		Title()
			// TODO liste des podcasts
    		 } 
        }
     }
}

Dans la fonctionsetContent, qui, pour rappel, définit le contenu visuel de l’activité, nous avons positionné la fonction  MaterialTheme.  Celle-ci englobe le composantTitleprécédemment créé. Notez que c’est ici aussi que nous positionnerons plus tard la liste des podcasts. La fonctionMaterialThemeprend les trois paramètrescolors,typographyetshape. Pour le moment, c’est des TODO mais il est temps de les remplacer.

Personnalisez les paramètres de la fonction composableMaterialTheme 

Pour spécifier la palette de couleurs, les typographies et les formes, plusieurs fonctions sont à votre disposition.

Fonctions et exemples

lightColors etdarkColorspermettent de définir les couleurs de l’application selon le mode clair ou sombre de l’appareil de l’utilisateur.

private val DarkColorScheme = darkColorScheme(
   primary = Color(0xFFD0BCFF),
   secondary = Color(0xFFCCC2DC),
   tertiary = Color(0xFFEFB8C8),
   /*etc ...*/
)

La classe Typographyprend en paramètre un objet de typeTextStylepermettant de définir chaque typographie sémantique.

val Typography = Typography(
    bodyLarge = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Normal,
        fontSize = 16.sp,
        lineHeight = 24.sp,
        letterSpacing = 0.5.sp
    ),
   bodyMedium = /**/,
/* etc ...*/

La classeShapesprend en paramètre un objet de typeCornerBasedShapeafin de définir chaque forme sémantique.

private val shapes = Shapes(
   extraSmall = RoundedCornerShape(4.dp),
   small = RoundedCornerShape(8.dp),
   /*etc ...*/
)

Jetez un coup d'œil dans le code de votre projet BestPodcast. Vous verrez qu’un thème Material a déjà été créé par défaut dans le fichierTheme.kt.  Vous y retrouverez aussi une fonction composableBestPodcastThemesimilaire à celle-ci.

@Composable
fun BestPodcastTheme(
   darkTheme: Boolean = isSystemInDarkTheme(),
   content: @Composable () -> Unit
) {
   val colorScheme = when {
       darkTheme -> DarkColorScheme
       else -> LightColorScheme
   }
   MaterialTheme(
       colorScheme = colorScheme,
       typography = Typography,
       content = content
   )
}
  • La fonctionBestPodcastThemea un paramètredarkThemequi grâce à la fonctionisSystemInDarkThemepermet de déterminer si le mode sombre est activé ou non sur l’appareil de l’utilisateur.

  • Ensuite, en fonction du paramètredarkTheme, elle applique la palette de couleurs appropriée ainsi qu’une typographie. Les formes ici ne sont pas spécifiées, c’est donc les formes définies par défaut dans Material qui seront utilisées. 

  • Vous pouvez remarquer queBestPodcastThemeest directement utilisé dans votre classeMainActivity.

Appliquez un thème Material pour les prévisualisations

Il est important d’appliquer également un thème Material au sein des prévisualisations, pour refléter le rendu réel des composants.

@Preview
@Composable
fun PreviewPodcastItemOnline() {
   BestPodcastTheme {
       PodcastItem(
           podcast = PodcastFactory.makePodcasts()[0],
           onDownloadClicked = {},
        )
   }
}

Selon les composants qui peuplent votre interface, certains composants vont hériter automatiquement (sans que vous n’ayez rien à faire) des caractéristiques de votre thème. Voici une liste non exhaustive de propriétés qui seront héritées implicitement :

  •  Si vous utilisez un composantButton, par défaut, sa couleur de fond appliquera la couleurprimary, sa forme correspondra à la forme sémantiquefull, etc.

  • Le composantTextpar défaut appliquera la typographiebodyLarge.

  • Les composants Material structurants comme les composantsCard,FloatingActionButton,Dialogappliqueront respectivement les formesmedium,largeetextraLarge.

  • etc…

Pour observer cet héritage implicite, reprenons la prévisualisationPreviewPodcastItemOnlineet changeons un peu la taille de la typographiebodyLargedu thèmeBestPodcast . La taille du titre du podcast devrait changer. 

Mais comment faire pour appliquer un autre style de typographie quebodyLarge

Pour cela, nous allons utiliser l’objetMaterialTheme.

Accédez aux attributs de Thème via l’objetMaterialTheme

L'objetMaterialTheme, à ne pas confondre avec la fonctionMaterialThemeque nous venons de voir, permet d'accéder individuellement à chaque propriété définie dans notre thème. Voici comment accéder à certaines propriétés :

  • MaterialTheme.colorScheme.primarypour obtenir la couleur sémantiqueprimary.

  • MaterialTheme.typography.titleLargepour obtenir la typographie de typetitleLarge.

  • MaterialTheme.shapes.small pour obtenir la forme de type Small.

Pour appliquer, par exemple, la typographietitleMediumet la couleurprimaryau composantTextprésent dans notre composantPodcastItem, il faut écrire :

fun PodcastItem(
   podcast: Podcast,
   onDownloadClicked: () -> Unit,
) {
   Row {
       /*...*/
       Text(
           text = podcast.title,
         modifier = Modifier.weight(1f),
           color = MaterialTheme.colorScheme.primary,
           style = MaterialTheme.typography.titleMedium,
       )
       when (podcast.downloadStatus) {
		/*...*/
       }
   }
}

Voici une vidéo dans laquelle vous verrez comment utiliser l’outil Material Theme Builder pour générer un thème, organiser les différents fichiers qui définissent ce thème et l’utiliser dans le code.

À vous de jouer !

Contexte

C’est parti pour l’atelier peinture de ce cours. Sortez vos gouaches et vos pinceaux numériques, vous allez donner du style à votre application BestPodcast en lui construisant et en y intégrant un thème.

Consignes

1. Pour vous assurer que vos composants sont stylisés de la même manière, appliquez le thème  BestPodcastTheme à toutes vos prévisualisations.

2. À l’aide du site Material Theme Builder, construisez votre thème

  • Sélectionnez les couleurs sémantiques de base de votre choix (vous pouvez même fournir une photo et demander au site de générer la palette sémantique en fonction de celle-ci).

  • Observez bien la prévisualisation de votre palette un peu plus bas sur la page. Elle vous aidera à choisir les bonnes couleurs pour votre application.

  • Sélectionnez des polices d’écritures personnalisées si vous le souhaitez.

     

  • Exportez le thème en cliquant sur le boutonExport theme et en sélectionnant  Jetpack Compose .

3. Intégrez le thème généré à l’application "BestPodcast" :

  • Intégrez les couleurs. Notez que l'exportation génère plusieurs palettes selon différents niveaux de contraste. Récupérez seulement une palette sombre et une palette claire et remplacez la palette actuellement utilisée dans le projet.

  • Intégrez la typographie. Android Studio devrait vous inviter à intégrer la dépendance à Google Font. N’oubliez pas non plus de copier-coller le fichierfont_certs.xmldans un répertoire values-v23 dans les ressources de l’application.

  • Supprimer le code relatif auxdynamicColors.

4. Appliquez les couleurs, typographies et formes de votre thème aux différents éléments du composant PodcastItem. Vous êtes libre des choix que vous ferez. Mais vous devez personnaliser :

  • La couleur de fond du composant, en utilisant le paramètremodifierdu layoutRow. Par exemple :  Row(modifier = Modifier.background(/*...*/) { /*...*/ }).

  • La forme du logo du podcast, en appliquant par exemple la formesmallvia le modifierclip().

  • La couleur et le style du titre du podcast, via les paramètrescoloretstyle , en appliquant par exemple respectivement la couleur sémantiquesecondary et la typographie  titleMedium .

  • La teinte des icônes de téléchargement via le paramètretint, en appliquant par exemple la couleurprimary.

  • La couleur de fond du bouton icône permettant de télécharger le podcast, en le passant de  Color.Yellow à la couleur sémantiquesurfaceVariantpar exemple.

Livrables

Votre projet sur Android Studio doit être conforme aux consignes ci-dessus.

En résumé

  • Jetpack Compose permet d’appliquer facilement un thème respectant la spécification Material Design grâce à la fonctionMaterialThemeet à l’objetMaterialTheme.

  • La fonctionMaterialThemepermet de personnaliser trois aspects d'un style Material : la palette de couleurs, les typographies et les formes utilisées.

  • Pour appliquer ces styles à une application, il suffit d’envelopper le composant parent avec la fonctionMaterialTheme.

  • Lorsque l’on utilise des composants Material commeText,TextField, etButtondans les enfants de ce composant parent, certaines propriétés sont héritées implicitement de ce thème.

  • Pour affecter spécifiquement certaines propriétés du thème à un composant, il faut utiliser l’objetMaterialTheme.

 Vous savez maintenant créer des composants unitairement. Maintenant il est temps d’apprendre à les agencer les uns avec les autres et à harmoniser leur mise en page.

Exemple de certificat de réussite
Exemple de certificat de réussite