Aby dostosować sposób działania animacji przejścia elementu współdzielonego, możesz użyć kilku parametrów, które umożliwiają zmianę sposobu przejścia.
Specyfikacja animacji
Aby zmienić specyfikację animacji używaną do zmiany rozmiaru i pozycji, możesz podać inny parametr boundsTransform
w pliku Modifier.sharedElement()
.
To zapewnia początkową pozycję Rect
i docelową pozycję Rect
.
Aby na przykład tekst z poprzedniego przykładu przesuwał się wraz z łukiem
motion, określ parametr boundsTransform
, by użyć specyfikacji 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 ) )
Możesz użyć dowolnego elementu AnimationSpec
. W tym przykładzie użyto specyfikacji keyframes
.
boundsTransform
parametryTryb zmiany rozmiaru
Podczas animacji między 2 współdzielonemi granicami możesz ustawić parametr resizeMode
na wartość RemeasureToBounds
lub ScaleToBounds
. Ten parametr określa sposób przechodzenia elementu wspólnego między tymi dwoma stanami. ScaleToBounds
najpierw mierzy układ podrzędny z zastosowaniem ograniczeń wyprzedzających (lub docelowych). Później
stabilny układ dziecka jest skalowany tak, aby pasował do wspólnych granic.
ScaleToBounds
można traktować jako „skala graficzna” między stanami.
Natomiast RemeasureToBounds
ponownie mierzy i układa układ podrzędnego elementu sharedBounds
z animowanymi stałymi ograniczeniami na podstawie docelowego rozmiaru.
ponowny pomiar jest wyzwalany przez zmianę rozmiaru granic, co może potencjalnie
każdej klatki.
W przypadku komponentów Text
zalecamy użycie ScaleToBounds
, ponieważ zapobiegnie to ponownemu rozmieszczaniu i przepływaniu tekstu na inne wiersze. W przypadku granic o różnych aspektach
współczynnik proporcji, a jeśli zależy Ci na płynności między dwoma wspólnymi elementami,
Zalecamy RemeasureToBounds
.
Różnicę między tymi dwoma trybami zmiany rozmiaru widać w poniższych przykładach:
|
|
---|---|
Przejdź do układu końcowego
Domyślnie podczas przechodzenia między 2 układami rozmiar układu przechodzi od stanu początkowego do końcowego. Może to być niepożądane, gdy animowanie treści, np. tekstu.
Poniższy przykład ilustruje tekst opisu „Lorem Ipsum” Wprowadzanie
na dwa różne sposoby. W pierwszym przykładzie tekst jest przeformatowywany, gdy wchodzi do kontenera, który zwiększa swój rozmiar, a w drugim przykładzie tekst nie jest przeformatowywany, gdy rośnie. Dodanie tych elementów (Modifier.skipToLookaheadSize()
) uniemożliwi przeformatowanie
w miarę wzrostu.
Bez modyfikatora skipToLookahead() – zwróć uwagę na przepływ tekstu „Lorem Ipsum” |
Modifier.skipToLookahead() – zwróć uwagę, że tekst „Lorem Ipsum” zachowuje swój ostatni stan na początku animacji. |
---|---|
Klip i nakładki
Podczas tworzenia elementów współdzielonych w komponencie należy pamiętać, że aby można było je udostępniać między różnymi komponentami, renderowanie komponentu jest podnoszone do nakładki warstwy, gdy rozpoczyna się przejście do jego odpowiednika na stronie docelowej. W efekcie będą one granice elementu nadrzędnego i przekształcenia warstwy (np. alfa i skala).
Element będzie renderowany na wierzchu innych nieudostępnionych elementów interfejsu. Po zakończeniu przejścia element zostanie przeniesiony z nakładki do własnej DrawScope
.
Aby przyciąć udostępniony element do kształtu, użyj standardowego Modifier.clip()
. Umieść go po elemencie 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 )
Jeśli chcesz mieć pewność, że udostępniony element nigdy nie będzie renderowany poza nadrzędnym kontenerem, możesz ustawić clipInOverlayDuringTransition
w sharedElement()
. Według
domyślnie, w przypadku zagnieżdżonych wspólnych granic, clipInOverlayDuringTransition
używa klipu
ścieżkę z elementu nadrzędnego sharedBounds()
.
Możliwość zachowania określonych elementów interfejsu, takich jak dolny pasek czy pływający element.
zawsze na górze podczas przejścia elementu udostępnianego, użyj
Modifier.renderInSharedTransitionScopeOverlay()
Domyślnie ta wartość
powoduje, że treść jest wyświetlana na nakładce w czasie, gdy jest udostępniana
przejście jest aktywne.
Na przykład w Jetsnak element BottomAppBar
musi być umieszczony na szczycie elementu współdzielonego, dopóki ekran nie stanie się niewidoczny. Dodawanie modyfikatora
kompozycyjne, pozostaje w górę.
Bez: |
Przez: |
---|---|
Czasami możesz chcieć, aby nieudostępnione komponenty były animowane i pozostawały na wierzchu innych komponentów przed przejściem. W takich przypadkach użyj funkcji renderInSharedTransitionScopeOverlay().animateEnterExit()
, aby animować kompozyt podczas przejścia elementu współdzielonego:
JetsnackBottomBar( modifier = Modifier .renderInSharedTransitionScopeOverlay( zIndexInOverlay = 1f, ) .animateEnterExit( enter = fadeIn() + slideInVertically { it }, exit = fadeOut() + slideOutVertically { it } ) )
W rzadkich przypadkach, gdy nie chcesz, aby udostępniony element był renderowany w nakładce, możesz ustawić wartość false (fałsz) dla atrybutu renderInOverlayDuringTransition
w elementach sharedElement()
.
Powiadamianie układów równorzędnych o zmianach rozmiaru udostępnianych elementów
Domyślnie sharedBounds()
i sharedElement()
nie informują kontenera nadrzędnego o żadnych zmianach rozmiaru podczas przechodzenia między układami.
Aby propagować zmiany rozmiaru do kontenera nadrzędnego podczas jego przenoszenia,
zmień parametr placeHolderSize
na PlaceHolderSize.animatedSize
. Spowoduje to powiększenie lub pomniejszenie elementu. Wszystkie inne elementy układu reagują na tę zmianę.
|
(Zwróć uwagę, jak pozostałe elementy na liście przesuwają się w dół w odpowiedzi na rosnącą pozycję jednego elementu). |
---|---|