La struttura di transizione di Android consente di animare tutti i tipi di movimento in la tua UI fornendo i layout iniziale e finale. Puoi selezionare il tipo di animazione che preferisci, ad esempio le visualizzazioni con dissolvenza o di cambiare le dimensioni delle visualizzazioni, e il framework di transizione determina come animare dal layout iniziale a quello finale.
Il framework di transizione include le seguenti funzionalità:
- Animazioni a livello di gruppo: applicare effetti di animazione a tutte le visualizzazioni in una gerarchia di visualizzazioni.
- Animazioni integrate: usa animazioni predefinite per effetti comuni come dissolvenza in uscita o movimento.
- Supporto dei file di risorse: carica gerarchie e animazioni integrate dai file di risorse di layout.
- Callback del ciclo di vita: Ricevere callback che forniscono il controllo sull'animazione e sulla gerarchia processo di modifica.
Per un esempio di codice che si anima tra le modifiche al layout, consulta BasicTransizione.
La procedura di base per animare due layout è la seguente:
- Crea un oggetto
Scene
per layout iniziale e finale. Tuttavia, la scena del layout iniziale è viene spesso determinato automaticamente dal layout corrente. - Crea una
Transition
per definire il tipo di animazione desiderato. - Chiama
TransitionManager.go()
, e il sistema esegue l'animazione per scambiare i layout.
Il diagramma nella figura 1 illustra la relazione tra i tuoi layout, le scene, la transizione e l'animazione finale.
Crea una scena
Le scene memorizzano lo stato di una gerarchia di viste, incluse tutte le relative viste e i relativi i valori delle proprietà. Il framework delle transizioni può eseguire animazioni tra una e una scena finale.
Puoi creare scene da un layout di risorse o da un gruppo di viste nel codice. Tuttavia, la scena iniziale per la transizione viene spesso determinata automaticamente nell'interfaccia utente corrente.
Una scena può anche definire le azioni che vengono eseguite quando cambi scena. Questa funzione è utile per ripulire le impostazioni della vista per passare a una scena.
Crea una scena da una risorsa di layout
Puoi creare un'istanza Scene
direttamente da una risorsa di layout
. Utilizza questa tecnica quando la gerarchia delle visualizzazioni nel file è per lo più statica.
La scena risultante rappresenta lo stato della gerarchia delle visualizzazioni nel momento in cui
ha creato l'istanza Scene
. Se modifichi la gerarchia di visualizzazione,
ricreare la scena. Il framework crea la scena dall'intera vista
nella gerarchia del file. Non puoi creare una scena da parte di un file di layout.
Per creare un'istanza Scene
da un file di risorse di layout, recupera
la radice della scena dal layout come
ViewGroup
Quindi chiama il metodo
Scene.getSceneForLayout()
con la radice della scena e l'ID risorsa del file di layout che
contiene la gerarchia di visualizzazione della scena.
Definisci i layout per le scene
Gli snippet di codice nel resto di questa sezione mostrano come creare
scene diverse con lo stesso elemento principale scena. Gli snippet dimostrano inoltre
è possibile caricare più oggetti Scene
non correlati senza lasciare intendere che
sono correlate tra loro.
L'esempio è costituito dalle seguenti definizioni di layout:
- Il layout principale di un'attività con un'etichetta di testo e un elemento secondario
FrameLayout
- Un
ConstraintLayout
per la prima scena con due campi di testo. - Un
ConstraintLayout
per la seconda scena con gli stessi due campi di testo in in un ordine diverso.
L'esempio è progettato in modo che tutta l'animazione si verifichi all'interno del file secondario layout del layout principale per l'attività. L'etichetta di testo nel layout principale rimangono statici.
Il layout principale dell'attività è definito come segue:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/master_layout"> <TextView android:id="@+id/title" ... android:text="Title"/> <FrameLayout android:id="@+id/scene_root"> <include layout="@layout/a_scene" /> </FrameLayout> </LinearLayout>
Questa definizione di layout contiene un campo di testo e un FrameLayout
secondario per
nella radice della scena. Il layout della prima scena è incluso nel file di layout principale.
In questo modo l'app può visualizzarlo nell'interfaccia utente iniziale e caricarlo
in una scena, dato che il framework può caricare solo un intero file di layout
scena.
Il layout per la prima scena è definito come segue:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/scene_container" android:layout_width="match_parent" android:layout_height="match_parent" ></androidx.constraintlayout.widget.ConstraintLayout>
Il layout della seconda scena contiene gli stessi due campi di testo, con le gli stessi ID, posizionati in un ordine diverso. È definito come segue:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/scene_container" android:layout_width="match_parent" android:layout_height="match_parent" ></androidx.constraintlayout.widget.ConstraintLayout>
Genera scene dai layout
Dopo aver creato le definizioni dei due layout dei vincoli, puoi ottenere un scena per ciascuno di essi. In questo modo puoi passare da un'interfaccia utente configurazioni. Per ottenere una scena, devi fare riferimento alla radice della scena e al layout dell'ID risorsa.
Il seguente snippet di codice mostra come ottenere un riferimento alla radice della scena
crea due oggetti Scene
dai file di layout:
Kotlin
val sceneRoot: ViewGroup = findViewById(R.id.scene_root) val aScene: Scene = Scene.getSceneForLayout(sceneRoot, R.layout.a_scene, this) val anotherScene: Scene = Scene.getSceneForLayout(sceneRoot, R.layout.another_scene, this)
Java
Scene aScene; Scene anotherScene; // Create the scene root for the scenes in this app. sceneRoot = (ViewGroup) findViewById(R.id.scene_root); // Create the scenes. aScene = Scene.getSceneForLayout(sceneRoot, R.layout.a_scene, this); anotherScene = Scene.getSceneForLayout(sceneRoot, R.layout.another_scene, this);
Nell'app ora sono presenti due oggetti Scene
in base alla visualizzazione
gerarchie. Entrambe le scene utilizzano la radice scena definita dal
Elemento FrameLayout
in res/layout/activity_main.xml
.
Crea una scena nel codice
Puoi anche creare un'istanza Scene
nel codice da un
Oggetto ViewGroup
. Utilizzare questa tecnica quando modifichi le gerarchie delle viste
direttamente nel codice o quando le generi in modo dinamico.
Per creare una scena da una gerarchia di visualizzazioni nel codice, utilizza la classe
Scene(sceneRoot, viewHierarchy)
come costruttore. Chiamare questo costruttore equivale a chiamare il
Scene.getSceneForLayout()
quando hai già gonfiato un file di layout.
Il seguente snippet di codice mostra come creare un Scene
dall'elemento principale della scena e la gerarchia di visualizzazione della scena in
il tuo codice:
Kotlin
val sceneRoot = someLayoutElement as ViewGroup val viewHierarchy = someOtherLayoutElement as ViewGroup val scene: Scene = Scene(sceneRoot, viewHierarchy)
Java
Scene mScene; // Obtain the scene root element. sceneRoot = (ViewGroup) someLayoutElement; // Obtain the view hierarchy to add as a child of // the scene root when this scene is entered. viewHierarchy = (ViewGroup) someOtherLayoutElement; // Create a scene. mScene = new Scene(sceneRoot, mViewHierarchy);
Crea azioni scena
Il framework consente di definire azioni personalizzate della scena che il sistema esegue l'ingresso o l'uscita da una scena. In molti casi, la definizione di azioni scena personalizzate è non necessario, poiché il framework anima il passaggio da una scena all'altra automaticamente.
Le azioni scena sono utili per gestire questi casi:
- Per animare le visualizzazioni che non appartengono alla stessa gerarchia. Puoi animare le visualizzazioni le scene iniziale e finale usando le azioni di uscita e di ingresso.
- Per animare le visualizzazioni che il framework di transizioni non può animare automaticamente,
ad esempio oggetti
ListView
. Per ulteriori informazioni informazioni, consulta la sezione sulle limitazioni.
Per fornire azioni personalizzate per la scena, definisci le azioni come
Runnable
oggetti e passali al
Scene.setExitAction()
oppure Scene.setEnterAction()
funzioni. Il framework chiama la funzione setExitAction()
all'inizio
scena prima di eseguire l'animazione di transizione e setEnterAction()
sulla scena finale dopo aver eseguito l'animazione di transizione.
Applicare una transizione
Il framework di transizione rappresenta lo stile dell'animazione tra le scene con un
Transition
oggetto. Puoi creare un'istanza di un Transition
utilizzando
di grandi dimensioni, come
AutoTransition
e
Fade
oppure
definisci la tua transizione.
Poi puoi eseguire
l'animazione tra le scene superando Scene
e Transition
a
TransitionManager.go()
.
Il ciclo di vita della transizione è simile al ciclo di vita dell'attività e rappresenta la transizione stabilisce che il framework monitora l'inizio completamento di un'animazione. In stati importanti del ciclo di vita, il framework richiama di callback che puoi implementare per regolare l'interfaccia utente fasi diverse della transizione.
Crea una transizione
La sezione precedente mostra come creare scene che rappresentino lo stato
diverse gerarchie di oggetti View. Dopo aver definito le scene iniziali e finali,
Se vuoi passare da un oggetto all'altro, crea un oggetto Transition
che definisca un'animazione.
Il framework consente di specificare una transizione integrata in un file di risorse
e gonfiarlo nel codice oppure creare un'istanza di una transizione integrata
direttamente nel codice.
Classe | Tagga | Effetto |
---|---|---|
AutoTransition |
<autoTransition/> |
Transizione predefinita. Dissolvenza in uscita, spostamento, ridimensionamento e dissolvenza nelle visualizzazioni, in questo ordine. |
ChangeBounds |
<changeBounds/> |
Sposta e ridimensiona le visualizzazioni. |
ChangeClipBounds |
<changeClipBounds/> |
Acquisisce View.getClipBounds() prima e dopo la scena
modifiche e le anima durante la transizione. |
ChangeImageTransform |
<changeImageTransform/> |
Acquisisce la matrice di un ImageView prima e dopo la scena
lo modifichi e lo anima durante la transizione. |
ChangeScroll |
<changeScroll/> |
Acquisisce le proprietà di scorrimento dei target prima e dopo la scena la modifica e l'animazione delle modifiche. |
ChangeTransform |
<changeTransform/> |
Acquisisce la portata e la rotazione delle visualizzazioni prima e dopo il cambio di scena e anima queste modifiche durante la transizione. |
Explode |
<explode/> |
Tiene traccia delle modifiche alla visibilità delle visualizzazioni target all'inizio e alla fine e sposta le visualizzazioni dentro o fuori dai bordi della scena. |
Fade |
<fade/> |
Le visualizzazioni di fade_in calano.fade_out visualizzazioni in dissolvenza.fade_in_out (valore predefinito) esegue un fade_out seguito da
un fade_in .
|
Slide |
<slide/> |
Tiene traccia delle modifiche alla visibilità delle visualizzazioni target all'inizio e alla fine e sposta le visualizzazioni dentro o fuori da uno dei bordi della scena. |
Crea un'istanza di transizione da un file di risorse
Questa tecnica consente di modificare la definizione della transizione senza cambiare il codice della tua attività. Questa tecnica è utile anche per separare definizioni della transizione dal codice dell'applicazione, come mostrato nella sezione informazioni su come specificare più transizioni.
Per specificare una transizione integrata in un file di risorse, segui questi passaggi:
- Aggiungi la directory
res/transition/
al progetto. - Crea un nuovo file di risorsa XML all'interno di questa directory.
- Aggiungi un nodo XML per una delle transizioni integrate.
Ad esempio, il seguente file di risorse specifica la transizione Fade
:
<fade xmlns:android="http://schemas.android.com/apk/res/android" />
Il seguente snippet di codice mostra come gonfiare un'istanza Transition
all'interno
la tua attività da un file di risorse:
Kotlin
var fadeTransition: Transition = TransitionInflater.from(this) .inflateTransition(R.transition.fade_transition)
Java
Transition fadeTransition = TransitionInflater.from(this). inflateTransition(R.transition.fade_transition);
Crea un'istanza di transizione nel codice
Questa tecnica è utile per creare oggetti di transizione dinamicamente se modificare l'interfaccia utente nel codice e creare semplici transizioni integrate di Compute Engine con pochi parametri o nessun parametro.
Per creare un'istanza di una transizione integrata, richiama una delle istanze
nelle sottoclassi della classe Transition
. Ad esempio,
Il seguente snippet di codice crea un'istanza della transizione Fade
:
Kotlin
var fadeTransition: Transition = Fade()
Java
Transition fadeTransition = new Fade();
Applicare una transizione
In genere applichi una transizione per passare da una gerarchia di visualizzazione all'altra in risposta a un evento, come un'azione utente. Ad esempio, considera un'app di ricerca: Quando l'utente inserisce un termine di ricerca e tocca il pulsante di ricerca, l'app cambia a una scena che rappresenta il layout dei risultati durante l'applicazione di una transizione il pulsante di ricerca esce con dissolvenze e i risultati di ricerca.
Per cambiare scena durante l'applicazione di una transizione in risposta a un evento in
la tua attività, chiama la funzione della classe TransitionManager.go()
con
la scena e l'istanza di transizione da utilizzare per l'animazione, come mostrato nell'immagine
seguente snippet:
Kotlin
TransitionManager.go(endingScene, fadeTransition)
Java
TransitionManager.go(endingScene, fadeTransition);
Il framework cambia la gerarchia della visualizzazione all'interno della radice della scena con la vista gerarchia dalla scena finale durante l'esecuzione dell'animazione specificata di transizione. La scena iniziale è la fine dell'ultima una transizione. Se non ci sono transizioni precedenti, viene determinata la scena iniziale. automaticamente dallo stato corrente dell'interfaccia utente.
Se non specifichi un'istanza di transizione, il gestore di transizione può applicare
transizione automatica in modo ragionevole nella maggior parte delle situazioni. Per
ulteriori informazioni, consulta il riferimento API per
TransitionManager
.
Scegli viste target specifiche
Il framework applica le transizioni a tutte le visualizzazioni nella scena iniziale e finale
per impostazione predefinita. In alcuni casi, potresti voler applicare un'animazione solo a un sottoinsieme
di visualizzazioni in una scena. Il framework ti consente di selezionare viste specifiche che vuoi
si anima. Ad esempio, il framework non supporta l'animazione di modifiche a
ListView
oggetti, quindi non provare ad animarli durante una transizione.
Ogni vista animata dalla transizione è detta target. Puoi solo seleziona i target che fanno parte della gerarchia di visualizzazione associata a una scena.
Per rimuovere una o più visualizzazioni dall'elenco dei target, richiama il metodo
removeTarget()
prima di iniziare la transizione. Per aggiungere solo le viste specificate ai
di target, richiama il
addTarget()
personalizzata. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API per
Transition
.
Specifica più transizioni
Per ottenere il massimo impatto da un'animazione, abbinala al tipo di modifiche che tra una scena e l'altra. Ad esempio, se rimuovi alcune viste e aggiungi altre tra una scena e l'altra, un'animazione di dissolvenza in uscita o in entrata fornisce un'immagine indica che alcune visualizzazioni non sono più disponibili. Se sposti le viste su punti diversi dello schermo, è meglio animare il movimento in modo che gli utenti noteranno la nuova posizione delle viste.
Non è necessario scegliere una sola animazione, poiché il framework delle transizioni consente di combinare effetti di animazione in un set di transizioni che contiene un gruppo di singole transizioni integrate o personalizzate.
Per definire un set di transizioni da una raccolta di transizioni in XML, crea un
risorsa nella directory res/transitions/
ed elenca le transizioni in
l'elemento TransitionSet
. Ad esempio, il seguente snippet mostra come
specificare un set di transizioni che abbia lo stesso comportamento di AutoTransition
classe:
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android" android:transitionOrdering="sequential"> <fade android:fadingMode="fade_out" /> <changeBounds /> <fade android:fadingMode="fade_in" /> </transitionSet>
Per gonfiare il set di transizioni in un
Oggetto TransitionSet
in
il tuo codice, chiama
TransitionInflater.from()
nella tua attività. La classe TransitionSet
si estende dal
Transition
corso, per poterlo utilizzare con un gestore della transizione come qualsiasi altro
un'altra istanza Transition
.
Applicare una transizione senza scene
Modificare le gerarchie delle visualizzazioni non è l'unico modo per modificare l'interfaccia utente. Tu Puoi apportare modifiche anche aggiungendo, modificando e rimuovendo le viste secondarie all'interno nella gerarchia corrente.
Ad esempio, puoi implementare un'interazione di ricerca con
un unico layout. Iniziare con il layout che mostra un campo di immissione della ricerca e una ricerca
. Per modificare l'interfaccia utente in modo che mostrino i risultati, rimuovi il pulsante di ricerca
quando l'utente lo tocca chiamando il
ViewGroup.removeView()
e aggiungi i risultati di ricerca richiamando
ViewGroup.addView()
personalizzata.
Puoi utilizzare questo approccio se l'alternativa è avere due gerarchie che sono quasi identiche. Anziché creare e gestire due file di layout separati per una lieve differenza nell'interfaccia utente, è possibile avere un solo file di layout contenenti una gerarchia di viste modificata nel codice.
Se apporti modifiche all'interno della gerarchia di visualizzazione corrente in questo modo, non per creare una scena. Puoi invece creare e applicare una transizione tra due stati di una gerarchia di viste utilizzando una transizione ritardata. Questa funzionalità il framework di transizioni inizia con lo stato corrente della gerarchia di visualizzazione, le modifiche apportate alle sue visualizzazioni e applica una transizione che anima cambia quando il sistema ridisegna l'interfaccia utente.
Per creare una transizione ritardata all'interno di una gerarchia di visualizzazione singola, segui questi passaggi: passaggi:
- Quando si verifica l'evento che attiva la transizione, chiama il metodo
TransitionManager.beginDelayedTransition()
che fornisce la vista padre di tutte le viste da modificare e la transizione da utilizzare. Il framework archivia lo stato lo stato delle viste secondarie e i relativi valori delle proprietà. - Apporta le modifiche alle viste secondarie in base al tuo caso d'uso. Il framework registra le modifiche apportate alle viste secondarie e alle relative proprietà.
- Quando il sistema ridisegna l'interfaccia utente in base alle modifiche apportate, il parametro anima le modifiche tra lo stato originale e il nuovo stato.
L'esempio seguente mostra come animare l'aggiunta di una visualizzazione di testo a una visualizzazione della gerarchia utilizzando una transizione ritardata. Il primo snippet mostra il layout file di definizione:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/mainLayout" android:layout_width="match_parent" android:layout_height="match_parent" > <EditText android:id="@+id/inputText" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" /> ... </androidx.constraintlayout.widget.ConstraintLayout>
Lo snippet successivo mostra il codice che anima l'aggiunta della visualizzazione di testo:
Kotlin
setContentView(R.layout.activity_main) val labelText = TextView(this).apply { text = "Label" id = R.id.text } val rootView: ViewGroup = findViewById(R.id.mainLayout) val mFade: Fade = Fade(Fade.IN) TransitionManager.beginDelayedTransition(rootView, mFade) rootView.addView(labelText)
Java
private TextView labelText; private Fade mFade; private ViewGroup rootView; ... // Load the layout. setContentView(R.layout.activity_main); ... // Create a new TextView and set some View properties. labelText = new TextView(this); labelText.setText("Label"); labelText.setId(R.id.text); // Get the root view and create a transition. rootView = (ViewGroup) findViewById(R.id.mainLayout); mFade = new Fade(Fade.IN); // Start recording changes to the view hierarchy. TransitionManager.beginDelayedTransition(rootView, mFade); // Add the new TextView to the view hierarchy. rootView.addView(labelText); // When the system redraws the screen to show this update, // the framework animates the addition as a fade in.
Definisci i callback del ciclo di vita della transizione
Il ciclo di vita della transizione è simile al ciclo di vita dell'attività. Rappresenta
afferma che il framework monitora il periodo che intercorre tra una chiamata
alla funzione TransitionManager.go()
e il completamento
l'animazione. In stati importanti del ciclo di vita, il framework richiama i callback
definita dal TransitionListener
a riga di comando.
I callback del ciclo di vita della transizione sono utili, ad esempio, per copiare una vista
valore di una proprietà dalla gerarchia della vista iniziale a quella della vista finale
durante un cambio di scena. Non puoi semplicemente copiare il valore dalla visualizzazione iniziale
la vista nella gerarchia della vista finale, perché quest'ultima non è
gonfiato fino al completamento della transizione. Devi invece memorizzare il valore
in una variabile e quindi la copia nella gerarchia della vista finale quando il framework
ha terminato la transizione. Per ricevere una notifica al termine della transizione,
di implementare
TransitionListener.onTransitionEnd()
nella tua attività.
Per ulteriori informazioni, consulta la documentazione di riferimento dell'API per
TransitionListener
.
Limitazioni
Questa sezione elenca alcuni limiti noti del framework delle transizioni:
- Animazioni applicate a un
L'app
SurfaceView
potrebbe non essere visualizzata in modo corretto.SurfaceView
istanze vengono aggiornate da un thread non UI, quindi gli aggiornamenti potrebbero non essere sincronizzati con le animazioni di altre visualizzazioni. - Alcuni tipi specifici di transizione potrebbero non produrre l'effetto di animazione desiderato
quando applicato a una
TextureView
. - Classi che si estendono
AdapterView
, ad esempioListView
, gestire le visualizzazioni dei propri figli in modi incompatibili con il framework sulle transizioni. Se provi ad animare una visualizzazione basata suAdapterView
, il display del dispositivo potrebbe non rispondere più. - Se provi a ridimensionare una
TextView
con un'animazione, il testo compare in una nuova posizione prima che l'oggetto sia completamente viene ridimensionato. Per evitare questo problema, non animare il ridimensionamento delle viste che contengono testo.