Mit einigen Parametern lässt sich anpassen, wie die Übergangsanimation für gemeinsame Elemente abläuft.
Animationsspezifikation
Wenn Sie die Animationsspezifikation für die Größen- und Positionsänderung ändern möchten, können Sie unter Modifier.sharedElement()
einen anderen boundsTransform
-Parameter angeben.
So werden die Anfangs- und Zielposition von Rect
angegeben.Rect
Wenn sich der Text im vorherigen Beispiel beispielsweise in einem Bogen bewegen soll, 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 jeden AnimationSpec
verwenden. In diesem Beispiel wird eine keyframes
-Spezifikation verwendet.
boundsTransform
-ParameterModus zum Ändern der Größe
Wenn Sie zwischen zwei gemeinsamen Grenzen animieren, können Sie den Parameter resizeMode
auf RemeasureToBounds
oder ScaleToBounds
festlegen. Mit diesem Parameter wird festgelegt, wie das freigegebene Element zwischen den beiden Status übergeht. ScaleToBounds
misst zuerst das untergeordnete Layout mit den Vorschau- (oder Ziel-)Einschränkungen. Anschließend wird das stabile Layout des untergeordneten Elements so skaliert, dass es in die gemeinsamen Grenzen passt.
ScaleToBounds
kann als „grafische Skala“ zwischen den Zuständen betrachtet werden.
Im Gegensatz dazu wird bei RemeasureToBounds
das untergeordnete Layout von sharedBounds
mit animierten festen Einschränkungen basierend auf der Zielgröße neu gemessen und neu angeordnet. Die Neumessung wird durch die Änderung der Begrenzungsgröße ausgelöst, was potenziell bei jedem Frame der Fall sein kann.
Für Text
-Kompositionen wird ScaleToBounds
empfohlen, da dadurch ein Neulayout und ein Neufluss von Text auf verschiedene Zeilen vermieden wird. RemeasureToBounds
wird für Ränder mit unterschiedlichen Seitenverhältnissen empfohlen, wenn Sie eine fließende Kontinuität zwischen den beiden gemeinsamen Elementen wünschen.
Die Unterschiede zwischen den beiden Modi zum Ändern der Größe sind in den folgenden Beispielen zu sehen:
|
|
---|---|
Zum endgültigen Layout springen
Standardmäßig wird beim Übergang zwischen zwei Layouts die Layoutgröße zwischen dem Anfangs- und Endzustand animiert. Das kann bei der Animation von Inhalten wie Text unerwünscht sein.
Im folgenden Beispiel wird der Beschreibungstext „Lorem Ipsum“ auf zwei verschiedene Arten auf dem Bildschirm angezeigt. Im ersten Beispiel wird der Text neu angeordnet, wenn er eingegeben wird, da der Container größer wird. Im zweiten Beispiel wird der Text nicht neu angeordnet, wenn er länger wird. Wenn Sie Modifier.skipToLookaheadSize()
hinzufügen, wird das automatische Neuformatieren verhindert.
Nein |
|
---|---|
Clips und Overlays
Damit freigegebene Elemente zwischen verschiedenen Composeables freigegeben werden können, wird das Rendering des Composeables in ein Ebenen-Overlay verschoben, wenn der Übergang zu seiner Übereinstimmung im Ziel gestartet wird. Das hat zur Folge, dass die Grenzen des übergeordneten Elements und die Ebenentransformationen (z. B. Alpha und Skalierung) umgangen werden.
Es wird über anderen nicht freigegebenen UI-Elementen gerendert. Sobald der Übergang abgeschlossen ist, wird das Element aus dem Overlay in eine eigene DrawScope
verschoben.
Wenn Sie ein freigegebenes Element zu einer Form zuschneiden möchten, verwenden Sie die Standardfunktion Modifier.clip()
. Platzieren Sie 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 ein freigegebenes Element niemals außerhalb eines übergeordneten Containers gerendert werden soll, können Sie clipInOverlayDuringTransition
auf sharedElement()
setzen. Standardmäßig verwendet clipInOverlayDuringTransition
für verschachtelte gemeinsame Begrenzungen den Clippfad des übergeordneten Elements sharedBounds()
.
Wenn bestimmte UI-Elemente wie eine untere Leiste oder eine schwebende Aktionsschaltfläche während eines Übergangs von gemeinsamen Elementen immer oben bleiben sollen, verwenden Sie Modifier.renderInSharedTransitionScopeOverlay()
. Standardmäßig bleiben die Inhalte im Overlay, solange die gemeinsame Überblendung aktiv ist.
In Jetsnack muss das BottomAppBar
beispielsweise über dem gemeinsamen Element platziert werden, bis der Bildschirm nicht mehr sichtbar ist. Wenn Sie den Modifier zum Composeable hinzufügen, bleibt es hervorgehoben.
Ohne |
Mit |
---|---|
Sie können festlegen, dass das nicht freigegebene Composeable vor dem Übergang animiert wird und sich über den anderen Composeables befindet. Verwenden Sie in solchen Fällen renderInSharedTransitionScopeOverlay().animateEnterExit()
, um das Zusammenspiel der Elemente zu animieren, während die Überblendung des freigegebenen Elements ausgeführt wird:
JetsnackBottomBar( modifier = Modifier .renderInSharedTransitionScopeOverlay( zIndexInOverlay = 1f, ) .animateEnterExit( enter = fadeIn() + slideInVertically { it }, exit = fadeOut() + slideOutVertically { it } ) )
In seltenen Fällen kann es vorkommen, dass du das geteilte Element nicht in einem Overlay rendern möchtest. In diesem Fall kannst du renderInOverlayDuringTransition
auf sharedElement()
auf „False“ setzen.
Über Änderungen an der Größe gemeinsam genutzter Elemente benachrichtigen
Standardmäßig benachrichtigen sharedBounds()
und sharedElement()
den übergeordneten Container nicht über Größenänderungen während des Layoutübergangs.
Wenn Sie die Größenänderungen während der Übergänge an den übergeordneten Container weitergeben möchten, ä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 sich die anderen Elemente in der Liste nach unten bewegen, wenn ein Element größer wird. |
---|---|