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 eine beliebige AnimationSpec
verwenden. In diesem Beispiel wird eine keyframes
-Spezifikation verwendet.
Modus 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.
Bei RemeasureToBounds
wird 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 des Texts auf verschiedene Zeilen vermieden wird. Wenn die Grenzen unterschiedliche Seitenverhältnisse haben und Sie eine flüssige Kontinuität zwischen den beiden gemeinsamen Elementen wünschen, wird RemeasureToBounds
empfohlen.
Die Unterschiede zwischen den beiden Modi zum Ändern der Größe sind in den folgenden Beispielen zu sehen:
|
|
---|---|
Zum endgültigen Layout springen
Beim Übergang zwischen zwei Layouts wird die Layoutgröße zwischen dem Start- und dem Endzustand standardmäßig 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 umgebrochen, wenn er größer wird, wenn der Container größer wird. Im zweiten Beispiel wird der Text nicht automatisch angepasst, wenn er größer wird. Wenn Sie Modifier.skipToLookaheadSize()
hinzufügen, wird das automatische Neuformatieren verhindert.
Ohne Modifier.skipToLookahead() – beachten Sie, dass der Text „Lorem Ipsum“ neu formatiert wird |
Modifier.skipToLookahead(): Beachten Sie, dass der Text "Lorem Ipsum" zu Beginn der Animation seinen endgültigen Zustand beibehält. |
---|---|
Clips und Overlays
Ein wichtiges Konzept beim Erstellen gemeinsam genutzter Elemente in Compose ist, dass sie zwischen verschiedenen Compose-Elementen freigegeben werden können, wenn das Rendering des Compose-Elements in ein Ebenen-Overlay verschoben wird, wenn der Übergang zu seiner Übereinstimmung im Ziel gestartet wird. Das hat zur Folge, dass die Grenzen des übergeordneten Elements und seine Ebenentransformationen (z. B. Alpha und Skalierung) umgangen werden.
Es wird über anderen nicht geteilten UI-Elementen gerendert. Nach Abschluss des Übergangs wird das Element vom Overlay in sein eigenes DrawScope
-Element 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 sharedBounds()
.
Wenn Sie möchten, dass bestimmte UI-Elemente wie eine Leiste oder eine unverankerte Aktionsschaltfläche während eines Übergangs mit gemeinsam genutzten Elementen immer oben im Vordergrund bleiben, verwenden Sie Modifier.renderInSharedTransitionScopeOverlay()
. Dieser Modifikator behält standardmäßig den Inhalt im Overlay bei, während der gemeinsame Übergang aktiv ist.
In Jetsnack muss BottomAppBar
beispielsweise so lange auf dem gemeinsam genutzten Element platziert werden, bis der Bildschirm nicht mehr sichtbar ist. Wenn Sie den Modifier zum Composeable hinzufügen, bleibt er hervorgehoben.
Ohne |
Mit |
---|---|
Manchmal möchten Sie, dass sich das nicht freigegebene Composeable wegbewegt und vor dem Übergang über den anderen Composeables bleibt. 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 } ) )
Falls Sie nicht möchten, dass ein geteiltes Element in einem Overlay gerendert wird, können Sie renderInOverlayDuringTransition
auf sharedElement()
auf „false“ setzen.
gleichgeordnete Layouts über Änderungen an gemeinsam genutzter Elementgröße 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 die anderen Elemente in der Liste als Reaktion auf das wachsende Element nach unten verschoben werden. |
---|---|