Aby dostosować sposób działania animacji przejścia elementu współdzielonego, możesz użyć kilku parametrów.
Specyfikacja animacji
Aby zmienić specyfikację animacji używaną do zmiany rozmiaru i pozycji, możesz podać inny parametr boundsTransform
w pliku Modifier.sharedElement()
.
W ten sposób określasz początkową pozycję Rect
i docelową pozycję Rect
.
Aby na przykład tekst w poprzednim przykładzie poruszał się po łuku, użyj parametru boundsTransform
, aby 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
.
Tryb 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ń wstecznych (lub docelowych). Następnie stabilny układ podrzędnego elementu jest skalowany, aby zmieścić się w ramach współdzielonych.
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. Ponowne pomiary są wywoływane przez zmianę rozmiaru granic, która może potencjalnie nastąpić w każdej klatce.
W przypadku komponentów Text
zalecamy użycie ScaleToBounds
, ponieważ zapobiegnie to ponownemu rozmieszczaniu i przepływaniu tekstu na inne wiersze. Jeśli chcesz uzyskać płynne przejście między 2 elementami, których współczynniki proporcji są różne, zalecamy użycie 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 jest animowany między początkowym a końcowym stanem. Może to być niepożądane zachowanie podczas animowania treści, takich jak tekst.
W tym przykładzie tekst „Lorem Ipsum” pojawia się na ekranie na 2 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 Modifier.skipToLookaheadSize()
zapobiega przepływowi treści na inne wiersze w miarę wzrostu liczby wierszy.
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 wykracza poza granice obiektu nadrzędnego i jego przekształceń warstwy (np. alfa i skali).
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 standardowej funkcji Modifier.clip()
. Umieść go po 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 zostanie wyrenderowany poza nadrzędnym kontenerem, możesz ustawić clipInOverlayDuringTransition
w sharedElement()
. Domyślnie w przypadku zagnieżdżonych wspólnych zakresów clipInOverlayDuringTransition
używa ścieżki klipu z folderu nadrzędnego sharedBounds()
.
Aby podczas przejścia z elementu współdzielonego zachować określone elementy interfejsu, np. pasek dolny lub przycisk akcji pływającej, zawsze na górze, użyj Modifier.renderInSharedTransitionScopeOverlay()
. Domyślnie ten modyfikator zachowuje zawartość nakładki przez cały czas trwania wspólnej animacji przejścia.
Na przykład w Jetsnak element BottomAppBar
musi być umieszczony na szczycie elementu współdzielonego, dopóki ekran nie stanie się niewidoczny. Dodanie modyfikatora do kompozytowego powoduje, że pozostaje on w pozycji wysuniętej.
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ść parametru renderInOverlayDuringTransition
w elementach sharedElement()
na „false” (fałsz).
Powiadamianie układów wyższego rzędu o zmianach rozmiaru elementu współdzielonego
Domyślnie sharedBounds()
i sharedElement()
nie informują kontenera nadrzędnego o żadnych zmianach rozmiaru podczas przechodzenia między układami.
Aby rozpowszechnić zmiany rozmiaru w kontenerze nadrzędnym podczas przejścia, 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 inne elementy na liście przesuwają się w dół w odpowiedzi na wzrost jednego elementu) |
---|---|