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ą w przypadku zmiany rozmiaru i pozycji, możesz w elemencie Modifier.sharedElement()
podać inny parametr boundsTransform
.
W ten sposób określasz początkową pozycję Rect
i docelową pozycję Rect
.
Jeśli np. tekst z poprzedniego przykładu ma poruszać się po łuku, 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ć dowolnej wartości AnimationSpec
. W tym przykładzie użyto specyfikacji keyframes
.
Tryb zmiany rozmiaru
Podczas animowania między 2 wspólnymi granicami parametr resizeMode
możesz ustawić na 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.
Element ScaleToBounds
można określić jako „skalę graficzną” 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, która może obejmować każdą klatkę.
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 przy przechodzeniu między 2 układami rozmiar układu jest animowany między stanem początkowym i końcowym. 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ę zwiększania się ich liczby.
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 wykroczy poza granice obiektu 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 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 będzie renderowany poza kontenerem nadrzędnym, możesz ustawić clipInOverlayDuringTransition
w elemencie sharedElement()
. Domyślnie w przypadku zagnieżdżonych wspólnych zakresów clipInOverlayDuringTransition
używa ścieżki klipu z folderu nadrzędnego sharedBounds()
.
Aby zapewnić, że określone elementy interfejsu, np. dolna belka lub pływający przycisk, będą zawsze widoczne u góry podczas przejścia z użyciem elementu współdzielonego, 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 Jetsnackie element BottomAppBar
musi być umieszczony na szczycie elementu współdzielonego, dopóki ekran nie stanie się niewidoczny. Dodanie modyfikatora do składanego elementu powoduje, że pozostaje on podniesiony.
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 „fałsz”.
Powiadamianie układów równorzędnych o zmianach rozmiaru udostępnianych elementów
Domyślnie sharedBounds()
i sharedElement()
nie powiadamią kontenera nadrzędnego o żadnych zmianach rozmiaru podczas przejść w ramach układu.
Aby zastosować zmiany rozmiaru do kontenera nadrzędnego podczas 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 inne elementy na liście przesuwają się w dół w odpowiedzi na wzrost jednego elementu) |
---|---|