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:material3
offre 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
,secondary
etonPrimary
. Cela est préférable à la dénomination basée sur la couleur elle-même, avec des noms descriptifs commeblueSky
,lavender
,olive
.
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
,typography
etshapes
sont optionnels. En l’absence de personnalisation, chaque paramètre a un style par défaut. Le quatrième paramètre content
est 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 composantTitle
précédemment créé. Notez que c’est ici aussi que nous positionnerons plus tard la liste des podcasts. La fonctionMaterialTheme
prend les trois paramètrescolors
,typography
etshape
. 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 |
|
La classe
|
La classe
|
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 composableBestPodcastTheme
similaire à 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 fonction
BestPodcastTheme
a un paramètredarkTheme
qui grâce à la fonctionisSystemInDarkTheme
permet de déterminer si le mode sombre est activé ou non sur l’appareil de l’utilisateur.Ensuite, en fonction du paramètre
darkTheme
, 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 que
BestPodcastTheme
est 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 composant
Button
, par défaut, sa couleur de fond appliquera la couleurprimary
, sa forme correspondra à la forme sémantiquefull
, etc.Le composant
Text
par défaut appliquera la typographiebodyLarge
.Les composants Material structurants comme les composants
Card
,FloatingActionButton
,Dialog
appliqueront respectivement les formesmedium
,large
etextraLarge
.etc…
Pour observer cet héritage implicite, reprenons la prévisualisationPreviewPodcastItemOnline
et changeons un peu la taille de la typographiebodyLarge
du 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 fonctionMaterialTheme
que 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.primary
pour obtenir la couleur sémantiqueprimary
.MaterialTheme.typography.titleLarge
pour obtenir la typographie de typetitleLarge
.MaterialTheme.shapes.small
pour obtenir la forme de type Small.
Pour appliquer, par exemple, la typographietitleMedium
et la couleurprimary
au composantText
pré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 fichier
font_certs.xml
dans un répertoire values-v23 dans les ressources de l’application.Supprimer le code relatif aux
dynamicColors
.
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ètre
modifier
du layoutRow
. Par exemple :Row(modifier = Modifier.background(/*...*/) { /*...*/ })
.La forme du logo du podcast, en appliquant par exemple la forme
small
via le modifierclip()
.La couleur et le style du titre du podcast, via les paramètres
color
etstyle
, en appliquant par exemple respectivement la couleur sémantiquesecondary
et la typographietitleMedium
.La teinte des icônes de téléchargement via le paramètre
tint
, 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émantiquesurfaceVariant
par 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 fonction
MaterialTheme
et à l’objetMaterialTheme
.La fonction
MaterialTheme
permet 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 fonction
MaterialTheme
.Lorsque l’on utilise des composants Material comme
Text
,TextField
, etButton
dans 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’objet
MaterialTheme
.
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.