Pour personnaliser l'exécution de l'animation de transition d'élément partagé, vous pouvez utiliser quelques paramètres pour modifier la transition des éléments partagés.
Spécification d'animation
Pour modifier la spécification d'animation utilisée pour le mouvement de taille et de position, vous pouvez spécifier un paramètre boundsTransform
différent sur Modifier.sharedElement()
.
Cela fournit la position Rect
initiale et la position Rect
cible.
Par exemple, pour que le texte de l'exemple précédent se déplace en arc, spécifiez le paramètre boundsTransform
pour utiliser une spécification keyframes
:
val textBoundsTransform = BoundsTransform { initialBounds, targetBounds -> keyframes { durationMillis = boundsAnimationDurationMillis initialBounds at 0 using ArcMode.ArcBelow using FastOutSlowInEasing targetBounds at boundsAnimationDurationMillis } } Text( "Cupcake", fontSize = 28.sp, modifier = Modifier.sharedBounds( rememberSharedContentState(key = "title"), animatedVisibilityScope = animatedVisibilityScope, boundsTransform = textBoundsTransform ) )
Vous pouvez utiliser n'importe quel AnimationSpec
. Cet exemple utilise une spécification keyframes
.
Mode Redimensionnement
Lorsque vous créez une animation entre deux limites partagées, vous pouvez définir le paramètre resizeMode
sur RemeasureToBounds
ou ScaleToBounds
. Ce paramètre détermine la façon dont l'élément partagé passe d'un état à l'autre. ScaleToBounds
mesure d'abord la mise en page enfant avec les contraintes d'anticipation (ou cible). La mise en page stable de l'enfant est ensuite mise à l'échelle pour s'adapter aux limites partagées.
ScaleToBounds
peut être considéré comme une "échelle graphique" entre les états.
Alors que RemeasureToBounds
re mesure et remet en page la mise en page enfant de sharedBounds
avec des contraintes fixes animées en fonction de la taille de la cible. La nouvelle mesure est déclenchée par le changement de taille des limites, qui peut se produire à chaque frame.
Pour les composables Text
, nous vous recommandons d'utiliser ScaleToBounds
, car cela permet d'éviter la remise en page et le reflow du texte sur différentes lignes. Pour les limites dont les proportions sont différentes et si vous souhaitez une continuité fluide entre les deux éléments partagés, RemeasureToBounds
est recommandé.
La différence entre les deux modes de redimensionnement est illustrée dans les exemples suivants:
|
|
---|---|
Passer à la mise en page finale
Par défaut, lors de la transition entre deux mises en page, la taille de la mise en page s'anime entre son état de début et son état final. Ce comportement peut être indésirable lors de l'animation de contenus tels que du texte.
L'exemple suivant illustre l'entrée du texte de description "Lorem Ipsum" à l'écran de deux manières différentes. Dans le premier exemple, le texte est réorganisé à mesure qu'il est saisi et que la taille du conteneur augmente. Dans le second exemple, le texte n'est pas réorganisé à mesure qu'il augmente. L'ajout de Modifier.skipToLookaheadSize()
empêche le reflow à mesure qu'il se développe.
Pas de Modifier.skipToLookahead() : le texte "Lorem Ipsum" est remodelé. |
Modifier.skipToLookahead() : notez que le texte "Lorem Ipsum" conserve son état final au début de l'animation. |
---|---|
Extrait et superpositions
Lors de la création d'éléments partagés dans Compose, un concept important est que, pour qu'ils puissent être partagés entre différents composables, le rendu du composable est élevé dans une superposition de calque lorsque la transition commence pour qu'il corresponde à la destination. L'effet est qu'il échappe aux limites du parent et à ses transformations de couche (par exemple, la valeur alpha et l'échelle).
Il s'affichera au-dessus d'autres éléments d'interface utilisateur non partagés. Une fois la transition terminée, l'élément sera supprimé de la superposition et placé dans sa propre DrawScope
.
Pour découper un élément partagé dans une forme, utilisez la fonction Modifier.clip()
standard. Placez-le après sharedElement()
:
Image( painter = painterResource(id = R.drawable.cupcake), contentDescription = "Cupcake", modifier = Modifier .size(100.dp) .sharedElement( rememberSharedContentState(key = "image"), animatedVisibilityScope = this@AnimatedContent ) .clip(RoundedCornerShape(16.dp)), contentScale = ContentScale.Crop )
Si vous devez vous assurer qu'un élément partagé ne s'affiche jamais en dehors d'un conteneur parent, vous pouvez définir clipInOverlayDuringTransition
sur sharedElement()
. Par défaut, pour les limites partagées imbriquées, clipInOverlayDuringTransition
utilise le chemin de découpe du sharedBounds()
parent.
Pour que des éléments d'interface utilisateur spécifiques, tels qu'une barre inférieure ou un bouton d'action flottant, restent toujours en haut lors d'une transition d'élément partagé, utilisez Modifier.renderInSharedTransitionScopeOverlay()
. Par défaut, ce modificateur conserve le contenu en superposition pendant que la transition partagée est active.
Par exemple, dans Jetsnack, le BottomAppBar
doit être placé au-dessus de l'élément partagé jusqu'à ce que l'écran ne soit pas visible. L'ajout du modificateur au composable le maintient en hauteur.
Sans |
Avec |
---|---|
Il peut arriver que vous souhaitiez que votre composable non partagé s'anime et reste au-dessus des autres composables avant la transition. Dans ce cas, utilisez renderInSharedTransitionScopeOverlay().animateEnterExit()
pour animer le composable pendant l'exécution de la transition d'élément partagé:
JetsnackBottomBar( modifier = Modifier .renderInSharedTransitionScopeOverlay( zIndexInOverlay = 1f, ) .animateEnterExit( enter = fadeIn() + slideInVertically { it }, exit = fadeOut() + slideOutVertically { it } ) )
Dans les rares cas où vous souhaitez que votre élément partagé ne s'affiche pas en superposition, vous pouvez définir renderInOverlayDuringTransition
sur sharedElement()
sur "false".
Informer les mises en page sœurs des modifications apportées à la taille des éléments partagés
Par défaut, sharedBounds()
et sharedElement()
n'informent pas le conteneur parent de toute modification de taille lors des transitions de mise en page.
Pour propager les modifications de taille au conteneur parent lors de la transition, remplacez le paramètre placeHolderSize
par PlaceHolderSize.animatedSize
. Cela entraîne une augmentation ou une réduction de l'élément. Tous les autres éléments de la mise en page réagissent à ce changement.
|
(Notez que les autres éléments de la liste se déplacent vers le bas en réponse à l'agrandissement de l'un d'entre eux.) |
---|---|