Aby dostosować sposób wyświetlania animacji przejścia elementów udostępnionych, możesz użyć kilku parametrów, które pozwalają zmienić sposób przejścia tych elementó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
.
Ta wartość określa początkową pozycję Rect
i docelową Rect
.
Aby np. tekst z poprzedniego przykładu 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
.
boundsTransform
Tryb zmiany rozmiaru
Podczas animowania między 2 wspólnymi granicami parametr resizeMode
możesz ustawić na RemeasureToBounds
lub ScaleToBounds
. Ten parametr określa, jak udostępniany element przechodzi między 2 stanami. ScaleToBounds
najpierw mierzy układ podrzędny z ograniczeniami z wyprzedzeniem (lub elementami docelowymi). Następnie stabilny układ dziecka zostaje przeskalowany, aby mieścił się we wspólnych granicach.
Element ScaleToBounds
można określić jako „skalę graficzną” między stanami.
Z kolei RemeasureToBounds
ponownie mierzy i przekazuje układ podrzędny elementu sharedBounds
z animowanymi stałymi ograniczeniami na podstawie rozmiaru docelowego. Ponowny pomiar jest wyzwalany przez zmianę rozmiaru granic, która może obejmować każdą klatkę.
W przypadku funkcji kompozycyjnych Text
zalecamy użycie ScaleToBounds
, ponieważ zapobiega on przekazywaniu i przekazywaniu tekstu w różnych wierszach. W przypadku granic o różnych współczynnikach proporcji lub jeśli zależy Ci na płynności między dwoma wspólnymi elementami, zalecamy użycie właściwości RemeasureToBounds
.
Różnica między tymi dwoma trybami widać w przykładach poniżej:
|
|
---|---|
Przejdź do ostatecznego układu
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, gdy animujesz treści (np. tekst).
Poniższy przykład pokazuje tekst opisu „Lorem Ipsum” wchodzący na ekran na 2 różne sposoby. W pierwszym przykładzie tekst zmienia się wraz ze wzrostem rozmiaru kontenera, a w drugim – tekst nie zmienia się wraz ze wzrostem. Dodanie dyrektywy Modifier.skipToLookaheadSize()
zapobiega ponownemu przepływowi w miarę jego wzrostu.
Brak Modifier.skipToLookahead() – zauważ zmianę przepływu tekstu „Lorem Ipsum” |
Modifier.skipToLookahead() – zwróć uwagę na to, że tekst „Lorem Ipsum” zachowuje końcowy stan na początku animacji. |
---|---|
Klip i nakładki
Istotną koncepcją przy tworzeniu udostępnionych elementów w funkcji Compose jest to, że aby mogły być one współużytkowane między różnymi elementami kompozycyjnymi, po rozpoczęciu przejścia do miejsca docelowego renderowanie elementu kompozycyjnego jest podwyższone do poziomu nakładki warstwy. W efekcie wykroczy poza granice obiektu nadrzędnego i przekształcenia warstw (np. alfa i skala).
Będzie się wyświetlał nad innymi nieudostępnionymi elementami interfejsu. Po zakończeniu przejścia element zostanie usunięty z nakładki do własnego elementu DrawScope
.
Aby przyciąć udostępniony element do kształtu, użyj standardowej funkcji Modifier.clip()
. Umieść go za elementem 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 granic clipInOverlayDuringTransition
używa ścieżki klipu z elementu nadrzędnego sharedBounds()
.
Aby określone elementy interfejsu, takie jak dolny pasek czy pływający przycisk polecenia, pozostawały zawsze na górze podczas przejścia do udostępnianego elementu, użyj właściwości Modifier.renderInSharedTransitionScopeOverlay()
. Domyślnie ten modyfikator utrzymuje treść w nakładce w czasie, gdy współdzielone przejście jest aktywne.
Na przykład w Jetnack obiekt BottomAppBar
musi być umieszczony na udostępnianym elemencie do momentu, gdy ekran nie będzie widoczny. Dodanie modyfikatora do funkcji kompozycyjnej sprawia, że element jest wyższy.
Bez: |
Przez: |
---|---|
Czasami możesz chcieć, aby Twoja nieudostępniona funkcja kompozycyjna była animowana poza innymi elementami kompozycyjnymi przed przejściem. W takich przypadkach użyj renderInSharedTransitionScopeOverlay().animateEnterExit()
, aby animować element kompozycyjny w miarę wykonywania przejścia ze wspólnego elementu:
JetsnackBottomBar( modifier = Modifier .renderInSharedTransitionScopeOverlay( zIndexInOverlay = 1f, ) .animateEnterExit( enter = fadeIn() + slideInVertically { it }, exit = fadeOut() + slideOutVertically { it } ) )
W rzadkich przypadkach, gdy nie chcesz, by udostępniany element był renderowany w nakładce, możesz w polu renderInOverlayDuringTransition
sharedElement()
ustawić wartość Fałsz.
Powiadamianie układów równorzędnych o zmianach rozmiaru udostępnianych elementów
Domyślnie sharedBounds()
i sharedElement()
nie powiadamiają kontenera nadrzędnego o zmianie rozmiaru podczas przechodzenia układu.
Aby zastosować zmiany rozmiaru do kontenera nadrzędnego podczas przenoszenia, zmień parametr placeHolderSize
na PlaceHolderSize.animatedSize
. Powoduje to powiększanie lub pomniejszanie elementu. Pozostałe 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). |
---|---|