Es gibt einige Parameter, mit denen Sie anpassen können, wie die Animation für den Übergang des gemeinsamen Elements abläuft.
Animationsspezifikation
Wenn Sie die für die Größen- und Positionsbewegung verwendete Animationsspezifikation ändern möchten, können Sie in Modifier.sharedElement()
einen anderen boundsTransform
-Parameter angeben.
So werden die ursprüngliche Rect
-Position und die Ziel-Rect
-Position angegeben.
Wenn Sie beispielsweise möchten, dass sich der Text im vorherigen Beispiel in einem Bogen bewegt, geben Sie für den Parameter boundsTransform
eine keyframes
-Spezifikation an:
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 ) )
Sie können einen beliebigen AnimationSpec
verwenden. In diesem Beispiel wird eine keyframes
-Spezifikation verwendet.
boundsTransform
-ParameterModus zum Ändern der Größe
Wenn Sie eine Animation zwischen zwei gemeinsam genutzten Grenzen erstellen, können Sie den Parameter resizeMode
auf RemeasureToBounds
oder ScaleToBounds
festlegen. Mit diesem Parameter wird festgelegt, wie die Übergänge des freigegebenen Elements zwischen den beiden Status erfolgen. ScaleToBounds
first
misst das untergeordnete Layout mit den Lookahead- oder Zielbeschränkungen. Das stabile Layout des Kindes wird dann so skaliert, dass es in die gemeinsamen Grenzen passt.
ScaleToBounds
kann als „grafische Skala“ zwischen den Status betrachtet werden.
Im Gegensatz dazu werden bei RemeasureToBounds
das untergeordnete Layout von sharedBounds
mit animierten festen Einschränkungen basierend auf der Zielgröße neu gemessen und neu angeordnet. Die erneute Messung wird durch die Änderung der Begrenzungsgröße ausgelöst, was potenziell in jedem Frame geschehen kann.
Für Text
-Composables wird ScaleToBounds
empfohlen, da dadurch ein erneutes Layout und Umfließen von Text in verschiedene Zeilen vermieden wird. RemeasureToBounds
wird für Grenzen mit unterschiedlichen Seitenverhältnissen empfohlen und wenn Sie einen fließenden Übergang zwischen den beiden gemeinsamen Elementen wünschen.
Der Unterschied zwischen den beiden Größenanpassungsmodi ist in den folgenden Beispielen zu sehen:
|
|
---|---|
Zum endgültigen Layout springen
Standardmäßig wird die Layoutgröße beim Übergang zwischen zwei Layouts zwischen dem Start- und dem Endstatus animiert. Das kann unerwünscht sein, wenn Sie Inhalte wie Text animieren.
Im folgenden Beispiel wird der Beschreibungstext „Lorem Ipsum“ auf zwei verschiedene Arten auf dem Bildschirm angezeigt. Im ersten Beispiel wird der Text umgebrochen, wenn der Container größer wird. Im zweiten Beispiel wird der Text nicht umgebrochen, wenn er länger wird. Durch das Hinzufügen von Modifier.skipToLookaheadSize()
wird verhindert, dass sich das Layout ändert, wenn die Anzeige größer wird.
Kein |
|
---|---|
Clips und Overlays
Damit freigegebene Elemente zwischen verschiedenen Composables geteilt werden können, wird das Rendern des Composables in eine Layer-Überlagerung verschoben, wenn der Übergang zum entsprechenden Element im Ziel beginnt. Dadurch wird die Ebene außerhalb der Grenzen des übergeordneten Elements und seiner Ebenentransformationen (z. B. Alpha und Skalierung) gerendert.
Es wird über anderen nicht freigegebenen UI-Elementen gerendert. Nach Abschluss der Übergangsphase wird das Element aus dem Overlay in einen eigenen DrawScope
verschoben.
Wenn Sie ein gemeinsames Element auf eine Form zuschneiden möchten, verwenden Sie die Standardfunktion Modifier.clip()
. Platziere es nach dem 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 )
Wenn Sie sicherstellen müssen, dass ein freigegebenes Element nie außerhalb eines übergeordneten Containers gerendert wird, können Sie clipInOverlayDuringTransition
für sharedElement()
festlegen. Standardmäßig wird für verschachtelte freigegebene Grenzen in clipInOverlayDuringTransition
der Beschneidungspfad des übergeordneten sharedBounds()
verwendet.
Wenn bestimmte UI-Elemente wie eine untere Leiste oder eine Floating Action Button während einer Shared Element-Übergangsanimation immer oben bleiben sollen, verwenden Sie Modifier.renderInSharedTransitionScopeOverlay()
. Standardmäßig wird mit diesem Modifikator der Inhalt im Overlay während der aktiven gemeinsamen Übergangszeit beibehalten.
In Jetsnack muss das BottomAppBar
beispielsweise über dem freigegebenen Element platziert werden, bis der Bildschirm nicht mehr sichtbar ist. Wenn Sie den Modifier dem Composable hinzufügen, bleibt er erhöht.
Ohne |
Mit |
---|---|
Möglicherweise soll das nicht freigegebene Composable nicht nur animiert werden, sondern auch vor dem Übergang über den anderen Composables bleiben. Verwenden Sie in solchen Fällen renderInSharedTransitionScopeOverlay().animateEnterExit()
, um die Composable-Funktion während der Übergangsanimation des gemeinsamen Elements zu animieren:
JetsnackBottomBar( modifier = Modifier .renderInSharedTransitionScopeOverlay( zIndexInOverlay = 1f, ) .animateEnterExit( enter = fadeIn() + slideInVertically { it }, exit = fadeOut() + slideOutVertically { it } ) )
In seltenen Fällen möchten Sie vielleicht nicht, dass Ihr gemeinsames Element in einem Overlay gerendert wird. In diesem Fall können Sie renderInOverlayDuringTransition
für sharedElement()
auf „false“ setzen.
Benachrichtigen von untergeordneten Layouts über Änderungen an der Größe des gemeinsam genutzten Elements
Standardmäßig werden sharedBounds()
und sharedElement()
nicht über Größenänderungen des übergeordneten Containers während des Layoutübergangs informiert.
Wenn Größenänderungen während der Übergangsphase auf den übergeordneten Container übertragen werden sollen, ändern Sie den Parameter placeHolderSize
in PlaceHolderSize.animatedSize
. Dadurch wird das Element vergrößert oder verkleinert. Alle anderen Elemente im Layout reagieren auf die Änderung.
|
Beachten Sie, wie die anderen Elemente in der Liste nach unten verschoben werden, wenn ein Element größer wird. |
---|---|