Aby dostosować sposób działania animacji przejścia elementu współdzielonego, możesz użyć kilku parametrów, które pozwolą zmienić sposób przejścia elementów współdzielonych.
Specyfikacja animacji
Aby zmienić specyfikację animacji używaną do przesuwania rozmiaru i pozycji, możesz określić inny parametr boundsTransform w pliku Modifier.sharedElement().
Podaje to początkową pozycję Rect i docelową pozycję Rect.
Aby na przykład tekst z poprzedniego przykładu poruszał się po łuku, użyj parametru boundsTransform, aby zastosować specyfikację 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 AnimationSpec. W tym przykładzie użyto specyfikacji keyframes.
boundsTransform parametryTryb zmiany rozmiaru
Podczas animowania między 2 wspólnymi granicami możesz ustawić parametr resizeMode na RemeasureToBounds lub ScaleToBounds. Ten parametr określa, jak element współdzielony przechodzi między dwoma stanami. ScaleToBounds najpierw mierzy układ elementu podrzędnego z użyciem ograniczeń wyprzedzających (lub docelowych). Następnie stabilny układ elementu podrzędnego jest skalowany tak, aby zmieścił się w udostępnionych granicach.
ScaleToBounds można traktować jako „skalę graficzną” między stanami.
Natomiast RemeasureToBounds ponownie mierzy i układa układ podrzędnysharedBounds z animowanymi stałymi ograniczeniami na podstawie rozmiaru docelowego. Ponowny pomiar jest wywoływany przez zmianę rozmiaru granic, co może następować w każdej klatce.
W przypadku komponentów kompozycyjnych Text zalecamy używanie ScaleToBounds, ponieważ pozwala to uniknąć ponownego układania i przelewania tekstu do innych wierszy. RemeasureToBounds jest zalecane w przypadku granic o różnych współczynnikach proporcji oraz jeśli chcesz uzyskać płynną ciągłość między 2 wspólnymi elementami.
Różnicę między tymi 2 trybami zmiany rozmiaru widać w przykładach poniżej:
|
|
|---|---|
Przejdź do układu końcowego
Domyślnie podczas przechodzenia między dwoma układami rozmiar układu jest animowany między stanem początkowym a końcowym. Może to być niepożądane zachowanie podczas animowania treści, takich jak tekst.
Poniższy przykład pokazuje tekst opisu „Lorem Ipsum” pojawiający się na ekranie na 2 różne sposoby. W pierwszym przykładzie tekst jest ponownie formatowany w miarę powiększania się kontenera. W drugim przykładzie tekst nie dopasowuje się do rozmiaru, gdy się powiększa. Dodanie Modifier.skipToLookaheadSize() zapobiega ponownemu przepływowi treści podczas powiększania.
Brak |
|
|---|---|
Klip i nakładki
Aby udostępniać elementy między różnymi funkcjami kompozycyjnymi, renderowanie funkcji kompozycyjnej jest przenoszone do nakładki warstwy, gdy rozpoczyna się przejście do pasującego elementu w miejscu docelowym. W efekcie element wyjdzie poza granice elementu nadrzędnego i jego przekształcenia warstwy (np. przezroczystość i skalę).
Będzie się wyświetlać nad innymi nieudostępnionymi elementami 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 znaku 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 na sharedElement(). Domyślnie w przypadku zagnieżdżonych udostępnionych granic funkcja clipInOverlayDuringTransition używa ścieżki przycinania z nadrzędnego elementu sharedBounds().
Aby podczas przejścia elementu udostępnionego zachować na wierzchu określone elementy interfejsu, takie jak pasek u dołu lub pływający przycisk działania, użyj Modifier.renderInSharedTransitionScopeOverlay(). Domyślnie ten modyfikator utrzymuje treść w nakładce w czasie, gdy aktywna jest udostępniona animacja przejścia.
Na przykład w aplikacji Jetsnack element BottomAppBar musi być umieszczony na elemencie współdzielonym, dopóki ekran nie będzie widoczny. Dodanie modyfikatora
do funkcji kompozycyjnej utrzymuje ją na wyższym poziomie.
Bez: |
Przez: |
|---|---|
Możesz chcieć, aby element kompozycyjny, który nie jest współdzielony, również znikał z animacją i pozostawał na wierzchu innych elementów kompozycyjnych przed przejściem. W takich przypadkach użyj funkcji renderInSharedTransitionScopeOverlay().animateEnterExit(), aby animować element kompozycyjny 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 chcesz, aby udostępniony element nie był renderowany w nakładce, możesz ustawić wartość renderInOverlayDuringTransition w sharedElement() na false.
Powiadamianie układów równorzędnych o zmianach rozmiaru elementu udostępnionego
Domyślnie elementy sharedBounds() i sharedElement() nie powiadamiają kontenera nadrzędnego o żadnych zmianach rozmiaru podczas przejść układu.
Aby zmiany rozmiaru były propagowane do kontenera nadrzędnego podczas przejścia, zmień parametr placeHolderSize na PlaceHolderSize.animatedSize. W ten sposób możesz powiększyć lub pomniejszyć element. Wszystkie pozostałe elementy układu reagują na zmianę.
|
(Zwróć uwagę, jak pozostałe elementy listy przesuwają się w dół, gdy jeden z nich się powiększa). |
|---|---|