Per personalizzare la modalità di esecuzione dell'animazione di transizione degli elementi condivisi, esistono alcuni parametri che possono essere utilizzati per modificare il modo in cui gli elementi condivisi vengono trasformati.
Specifiche animazione
Per modificare la specifica dell'animazione utilizzata per il movimento di dimensione e posizione, puoi specificare un parametro boundsTransform
diverso su Modifier.sharedElement()
.
Fornisce la posizione Rect
iniziale e la posizione Rect
target.
Ad esempio, per spostare il testo nell'esempio precedente con un'
animazione arco, specifica il parametro boundsTransform
per utilizzare una specifica 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 ) )
Puoi utilizzare qualsiasi AnimationSpec
. In questo esempio viene utilizzata una specifica keyframes
.
boundsTransform
Modalità Ridimensiona
Quando esegui l'animazione tra due limiti condivisi, puoi impostare il parametro resizeMode
su RemeasureToBounds
o ScaleToBounds
. Questo parametro determina la modalità di transizione
dell'elemento condiviso tra i due stati. ScaleToBounds
misura innanzitutto il layout secondario con i vincoli di lookahead (o target). Successivamente, il layout stabile del publisher secondario viene ridimensionato per rientrare nei limiti condivisi.
ScaleToBounds
può essere considerata come una "scala grafica" tra gli stati.
Mentre RemeasureToBounds
rimisura e riconfigura il layout secondario di sharedBounds
con vincoli fissi animati basati sulle dimensioni di destinazione. La nuova misurazione viene attivata dalla modifica delle dimensioni dei limiti, che potrebbe interessare ogni frame.
Per gli elementi componibili Text
, si consiglia l'uso di ScaleToBounds
perché eviterà il relayout
e l'adattamento dinamico del testo su righe diverse. Per i limiti che hanno proporzioni diverse e se vuoi una continuità fluida tra i due elementi condivisi, ti consigliamo di utilizzare RemeasureToBounds
.
La differenza tra le due modalità di ridimensionamento è evidente negli esempi riportati di seguito:
|
|
---|---|
Vai al layout finale
Per impostazione predefinita, quando passi da un layout all'altro, la dimensione del layout si anima tra lo stato iniziale e quello finale. Questo può essere un comportamento indesiderato durante l'animazione di contenuti come il testo.
L'esempio seguente illustra il testo descrittivo "Lorem Ipsum" che entra nella schermata in due modi diversi. Nel primo esempio, il testo viene adattato man mano che viene inserito man mano che il container aumenta, mentre nel secondo esempio il testo non viene adattato man mano che aumenta. L'aggiunta di Modifier.skipToLookaheadSize()
impedisce l'adattamento dinamico del contenuto
man mano che cresce.
No Modifier.skipToLookahead() - nota la ripetizione del flusso del testo "Lorem Ipsum" |
Modifier.skipToLookahead(): noterai che il testo "Lorem Ipsum" mantiene il suo stato finale all'inizio dell'animazione. |
---|---|
Clip e overlay
Un concetto importante durante la creazione di elementi condivisi in Compose è che, affinché possano essere condivisi tra diversi componibili, il rendering dell'elemento componibile viene elevato in un overlay del livello quando viene avviata la transizione in modo che corrisponda alla destinazione. Il risultato è l'uscita dai limiti del padre e dalle trasformazioni del livello (ad esempio alfa e scala).
Verrà visualizzato sopra altri elementi dell'interfaccia utente non condivisi. Al termine della transizione, l'elemento verrà rilasciato dall'overlay al proprio DrawScope
.
Per ritagliare un elemento condiviso in una forma, utilizza la funzione Modifier.clip()
standard. Posizionalo dopo 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 )
Se devi assicurarti che un elemento condiviso non venga mai eseguito al di fuori di un contenitore principale, puoi impostare clipInOverlayDuringTransition
su sharedElement()
. Per impostazione predefinita, per i limiti condivisi nidificati, clipInOverlayDuringTransition
utilizza il percorso del clip dell'elemento sharedBounds()
principale.
Per supportare la conservazione di elementi specifici dell'interfaccia utente, come una barra inferiore o un pulsante di azione mobile, sempre in primo piano durante una transizione di elementi condivisi, utilizza Modifier.renderInSharedTransitionScopeOverlay()
. Per impostazione predefinita, questo modificatore mantiene i contenuti nell'overlay durante il tempo in cui è attiva la transizione condivisa.
Ad esempio, in Jetsnack, BottomAppBar
deve essere posizionato sopra l'elemento condiviso finché lo schermo non è visibile. L'aggiunta del modificatore
al componibile lo mantiene elevato.
Senza |
Con |
---|---|
A volte potresti voler creare un componibile non condiviso che si anima e rimanga sopra gli altri componibili prima della transizione. In questi casi, utilizza renderInSharedTransitionScopeOverlay().animateEnterExit()
per animare il componibile durante l'esecuzione della transizione dell'elemento condiviso:
JetsnackBottomBar( modifier = Modifier .renderInSharedTransitionScopeOverlay( zIndexInOverlay = 1f, ) .animateEnterExit( enter = fadeIn() + slideInVertically { it }, exit = fadeOut() + slideOutVertically { it } ) )
Nel raro caso in cui tu non voglia che l'elemento condiviso venga visualizzato in un overlay, puoi impostare renderInOverlayDuringTransition
su sharedElement()
su false.
Invia una notifica ai layout di pari livello delle modifiche alle dimensioni dell'elemento condiviso
Per impostazione predefinita, sharedBounds()
e sharedElement()
non notificano al contenitore principale eventuali modifiche alle dimensioni durante le transizioni del layout.
Per propagare le modifiche alle dimensioni al contenitore principale durante la transizione, modifica il parametro placeHolderSize
in PlaceHolderSize.animatedSize
. In questo modo, l'elemento si ingrandisce o si riduce. Tutti gli altri elementi del layout
rispondono al cambiamento.
|
(nota come le altre voci nell'elenco vengono spostate verso il basso in risposta alla crescita di un elemento). |
---|---|