Dans Compose, vous pouvez enchaîner plusieurs modificateurs pour modifier l'apparence d'un composable. Ces chaînes de modificateurs peuvent avoir une incidence sur les contraintes transmises aux composables, qui définissent les limites de largeur et de hauteur.
Cette page explique comment les modificateurs enchaînés affectent les contraintes et, par conséquent, la mesure et le placement des composables.
Modificateurs dans l'arborescence de l'interface utilisateur
Pour comprendre comment les modificateurs s'influencent mutuellement, il est utile de visualiser leur apparence dans l'arborescence de l'interface utilisateur, qui est générée lors de la phase de composition. Pour en savoir plus, consultez la section Composition.
Dans l'arborescence de l'interface utilisateur, vous pouvez visualiser les modificateurs en tant que nœuds wrapper pour les nœuds de mise en page :
L'ajout de plusieurs modificateurs à un composable crée une chaîne de modificateurs. Lorsque vous enchaînez plusieurs modificateurs, chaque nœud de modificateur encapsule le reste de la chaîne et le nœud de mise en page. Par exemple, lorsque vous enchaînez un clip et un
size modificateur, le nœud de modificateur clip encapsule le nœud de modificateur size,
qui encapsule ensuite le nœud de mise en page Image.
Lors de la phase de mise en page, l'algorithme qui parcourt l'arborescence reste le même, mais chaque nœud de modificateur est également visité. De cette façon, un modificateur peut modifier les exigences de taille et le placement du modificateur ou du nœud de mise en page qu'il encapsule.
Comme illustré à la figure 2, l'implémentation des composables Image et Text eux-mêmes consiste en une chaîne de modificateurs encapsulant un seul nœud de mise en page.
Les implémentations de Row et Column sont des nœuds de mise en page qui décrivent comment disposer leurs enfants.
En résumé :
- Les modificateurs encapsulent un seul modificateur ou nœud de mise en page.
- Les nœuds de mise en page peuvent disposer plusieurs nœuds enfants.
Les sections suivantes décrivent comment utiliser ce modèle mental pour raisonner sur l'enchaînement des modificateurs et sur son influence sur la taille des composables.
Contraintes lors de la phase de mise en page
La phase de mise en page suit un algorithme en trois étapes pour trouver la largeur, la hauteur et les coordonnées x et y de chaque nœud de mise en page :
- Mesurer les enfants : un nœud mesure ses enfants, le cas échéant.
- Déterminer sa propre taille : en fonction de ces mesures, un nœud détermine sa propre taille.
- Placer les enfants : chaque nœud enfant est placé par rapport à la propre position d'un nœud.
Constraints permettent de trouver les tailles appropriées pour les nœuds lors des deux premières
étapes de l'algorithme. Les contraintes définissent les limites minimales et maximales de la largeur et de la hauteur d'un nœud. Lorsque le nœud détermine sa taille, sa taille mesurée doit se situer dans cette plage de tailles.
Types de contraintes
Une contrainte peut être l'une des suivantes :
- Limité : le nœud a une largeur et une hauteur maximales et minimales.
- Illimité : le nœud n'est pas limité à une taille spécifique. Les limites maximales de largeur et de hauteur sont définies sur l'infini.
- Exact : le nœud est invité à respecter une exigence de taille exacte. Les limites minimale et maximale sont définies sur la même valeur.
- Combinaison : le nœud suit une combinaison des types de contraintes précédents. Par exemple, une contrainte peut limiter la largeur tout en autorisant une hauteur maximale illimitée, ou définir une largeur exacte, mais fournir une hauteur limitée.
La section suivante décrit comment ces contraintes sont transmises d'un parent à un enfant.
Transmission des contraintes du parent à l'enfant
Lors de la première étape de l'algorithme décrit dans Contraintes lors de la phase de mise en page, les contraintes sont transmises du parent à l'enfant dans l'arborescence de l'interface utilisateur.
Lorsqu'un nœud parent mesure ses enfants, il fournit ces contraintes à chaque enfant pour lui indiquer la taille qu'il est autorisé à avoir. Ensuite, lorsqu'il détermine sa propre taille, il respecte également les contraintes transmises par ses propres parents.
De manière générale, l'algorithme fonctionne comme suit :
- Pour déterminer la taille qu'il souhaite réellement occuper, le nœud racine de l'arborescence de l'interface utilisateur mesure ses enfants et transmet les mêmes contraintes à son premier enfant.
- Si l'enfant est un modificateur qui n'a pas d'incidence sur la mesure, il transmet les contraintes au modificateur suivant. Les contraintes sont transmises telles quelles dans la chaîne de modificateurs, sauf si un modificateur ayant une incidence sur la mesure est atteint. Les contraintes sont ensuite redimensionnées en conséquence.
- Une fois qu'un nœud sans enfant est atteint (appelé "nœud terminal"), il détermine sa taille en fonction des contraintes transmises et renvoie cette taille résolue à son parent.
- Le parent adapte ses contraintes en fonction des mesures de cet enfant et appelle son enfant suivant avec ces contraintes ajustées.
- Une fois que tous les enfants d'un parent sont mesurés, le nœud parent détermine sa propre taille et la communique à son propre parent.
- De cette façon, l'ensemble de l'arborescence est parcouru en profondeur. Finalement, tous les nœuds ont déterminé leur taille et l'étape de mesure est terminée.
Pour obtenir un exemple détaillé, regardez la vidéo Constraints and modifier order (Contraintes et ordre des modificateurs).
Modificateurs qui affectent les contraintes
Dans la section précédente, vous avez appris que certains modificateurs peuvent affecter la taille des contraintes. Les sections suivantes décrivent des modificateurs spécifiques qui ont une incidence sur les contraintes.
Le modificateur size
Le size modificateur déclare la taille souhaitée du contenu.
Par exemple, l'arborescence de l'interface utilisateur suivante doit être affichée dans un conteneur de 300dp par 200dp. Les contraintes sont limitées, ce qui permet des largeurs comprises entre 100dp et 300dp, et des hauteurs comprises entre 100dp et 200dp :
Le modificateur size adapte les contraintes entrantes pour qu'elles correspondent à la valeur qui lui est transmise.
Dans cet exemple, la valeur est 150dp :
size ajustant les contraintes à 150dp.Si la largeur et la hauteur sont inférieures à la limite de contrainte la plus petite ou supérieures à la limite de contrainte la plus grande, le modificateur correspond aux contraintes transmises aussi précisément que possible tout en respectant les contraintes transmises :
size respectant la contrainte transmise aussi précisément que possible.Notez que l'enchaînement de plusieurs modificateurs size ne fonctionne pas. Le premier modificateur size définit les contraintes minimale et maximale sur une valeur fixe. Même si le deuxième modificateur de taille demande une taille plus petite ou plus grande, il doit toujours respecter les limites exactes transmises. Il ne remplace donc pas ces valeurs :
size, dans laquelle la deuxième valeur transmise (50dp) ne remplace pas la première valeur (100dp).Le modificateur requiredSize
Utilisez le requiredSize modificateur au lieu de size si vous avez besoin que votre
nœud remplace les contraintes entrantes. Le modificateur requiredSize remplace les contraintes entrantes et transmet la taille que vous spécifiez en tant que limites exactes.
Lorsque la taille est renvoyée dans l'arborescence, le nœud enfant est centré dans l'espace disponible :
requiredSize remplaçant les contraintes entrantes du modificateur size.Les modificateurs width et height
Le modificateur size adapte à la fois la largeur et la hauteur des contraintes. Avec le modificateur width, vous pouvez définir une largeur fixe, mais laisser la hauteur indéterminée.
De même, avec le modificateur height, vous pouvez définir une hauteur fixe, mais laisser la largeur indéterminée :
width et le modificateur height définissant respectivement une largeur et une hauteur fixes.Le modificateur sizeIn
Le modificateur sizeIn vous permet de définir des contraintes minimales et maximales exactes pour la largeur et la hauteur. Utilisez le modificateur sizeIn si vous avez besoin d'un contrôle précis sur les contraintes.
sizeIn avec minWidth, maxWidth, minHeight et maxHeight définis.Exemples
Cette section présente et explique la sortie de plusieurs extraits de code avec des modificateurs enchaînés.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .size(50.dp) )
Cet extrait génère la sortie suivante :
Image remplit la taille maximale en raison de la chaîne de modificateurs.- Le modificateur
fillMaxSizemodifie les contraintes pour définir la largeur et la hauteur minimales sur la valeur maximale :300dpen largeur et200dpen hauteur. - Même si le modificateur
sizesouhaite utiliser une taille de50dp, il doit toujours respecter les contraintes minimales entrantes. Le modificateursizegénère donc également les limites de contrainte exactes de300par200, en ignorant la valeur fournie dans le modificateursize. - L'
Imagesuit ces limites et signale une taille de300par200, qui est transmise jusqu'en haut de l'arborescence.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .wrapContentSize() .size(50.dp) )
Cet extrait génère la sortie suivante :
Image est centré et dimensionné à
50dp.- Le modificateur
fillMaxSizeadapte les contraintes pour définir la largeur et la hauteur minimales sur la valeur maximale :300dpen largeur et200dpen hauteur. - Le modificateur
wrapContentSizeréinitialise les contraintes minimales. Ainsi, alors quefillMaxSizea entraîné des contraintes fixes,wrapContentSizeles réinitialise sur des contraintes limitées. Le nœud suivant peut désormais occuper à nouveau tout l'espace ou être plus petit que l'espace entier. - Le modificateur
sizedéfinit les contraintes sur des limites minimales et maximales de50. - L'
Imageest résolue en une taille de50par50, et le modificateursizela transmet. - Le
wrapContentSizemodificateur possède une propriété spéciale. Il prend son enfant et le place au centre des limites minimales disponibles qui lui ont été transmises. La taille qu'il communique à ses parents est donc égale aux limites minimales qui lui ont été transmises.
En combinant seulement trois modificateurs, vous pouvez définir une taille pour le composable et le centrer dans son parent.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .clip(CircleShape) .padding(10.dp) .size(100.dp) )
Cet extrait génère la sortie suivante :
- Le modificateur
clipne modifie pas les contraintes. - Le modificateur
paddingréduit les contraintes maximales. - Le modificateur
sizedéfinit toutes les contraintes sur100dp. - L'
Imagerespecte ces contraintes et signale une taille de100dppar100dp. - Le modificateur
paddingajoute10dpsur tous les côtés à la taille signalée par l'Image. La mise en page avec marge intérieure signale donc une largeur et une hauteur de120dp. - Lors de la phase de dessin, le modificateur
clipagit sur un canevas de120dppar120dp. Il crée un masque circulaire de cette taille. - Le modificateur
paddinginsère ensuite son contenu de10dpsur tous les côtés, ce qui réduit la taille du canevas de l'Imageà100dppar100dp. - L'
Imageest dessinée dans ce canevas plus petit. L'image est découpée en fonction du cercle d'origine de120dp. Le résultat n'est donc pas rond.