Mit einigen Parametern lässt sich anpassen, wie die Übergangsanimation für gemeinsame Elemente abläuft.
Animationsspezifikation
Wenn Sie die für die Größen- und Positionsänderung verwendete Animationsspezifikation ä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.
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
Standardmäßig wird beim Übergang zwischen zwei Layouts die Layoutgröße zwischen dem Start- und dem Endstatus 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, während der Container größer wird. Im zweiten Beispiel wird der Text nicht neu angeordnet, 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(): Der Text „Lorem Ipsum“ behält seinen Endstatus zu Beginn der Animation bei. |
---|---|
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 freigegebenen UI-Elementen gerendert. Sobald die Umstellung abgeschlossen ist, wird das Element aus dem Overlay in sein eigenes 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 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 |
---|---|
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 } ) )
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. |
---|---|