Crea splendide transizioni con Material Motion per Android

1. Introduzione

Material Design è un sistema per la creazione di prodotti digitali belli e audaci. Unendo stile, branding, interazione e movimento in un insieme coerente di principi e componenti, i team di prodotto possono realizzare il loro massimo potenziale di progettazione.

logo_components_color_2x_web_96dp.png

Material Components (MDC) consente agli sviluppatori di implementare Material Design. Creato dal team di ingegneri e designer UX di Google, MDC è dotato di decine di componenti UI belli e funzionali ed è disponibile per Android, iOS, web e Flutter.material.io/develop

Cos'è il sistema di movimento di Material per Android?

Il sistema di movimento Material per Android è un insieme di modelli di transizione all'interno della libreria MDC-Android che possono aiutare gli utenti a comprendere e navigare in un'app, come descritto nelle linee guida di Material Design.

I quattro principali modelli di transizione Material sono i seguenti:

  • Trasformazione container: transizioni tra elementi UI che includono un contenitore. crea una connessione visibile tra due elementi distinti dell'interfaccia utente trasformando in modo fluido un elemento in un altro.
  • Asse condiviso: transizioni tra elementi UI che hanno una relazione spaziale o di navigazione. utilizza una trasformazione condivisa sugli assi x, y o z per rafforzare la relazione tra gli elementi.
  • Dissolvenza attraverso: transizioni tra elementi UI che non hanno una forte relazione tra loro. utilizza una dissolvenza in entrata e in uscita sequenziale, con una scala dell'elemento in entrata.
  • Dissolvenza: utilizzata per gli elementi UI che entrano o escono entro i margini dello schermo.

La libreria MDC-Android offre classi di transizione per questi pattern, basate sia sulla libreria AndroidX Transizione (androidx.transition) sia su Android Transizione Framework (android.transition):

AndroidX

  • Disponibile nel pacchetto com.google.android.material.transition
  • Supporta il livello API 14 o versioni successive
  • Supporta frammenti e viste, ma non attività o finestre
  • Contiene correzioni di bug con backporting e un comportamento coerente tra i livelli API

Framework

  • Disponibile nel pacchetto com.google.android.material.transition.platform
  • Supporta il livello API 21 o versioni successive
  • Supporta frammenti, viste, attività e finestre
  • Correzioni di bug non sottoposte a backporting e che potrebbero avere comportamenti diversi nei livelli API

In questo codelab, utilizzerai le transizioni Material basate sulla libreria AndroidX, il che significa che ti concentrerai principalmente su Frammenti e Viste.

Cosa creerai

Questo codelab ti guiderà nella creazione di alcune transizioni in un'app email per Android di esempio chiamata Rispondi, utilizzando Kotlin, per dimostrare come utilizzare le transizioni dalla libreria MDC-Android per personalizzare l'aspetto e il design della tua app.

Ti verrà fornito il codice di avvio per l'app di Reply e incorporerai nell'app le seguenti transizioni di tipo Material, che puoi vedere nella GIF completa del codelab qui sotto:

  • Transizione di Container Transform dalla mailing list alla pagina dei dettagli delle email
  • Transizione di Container Transform da FAB alla pagina di scrittura delle email
  • Transizione sull'asse Z condivisa dall'icona di ricerca alla pagina di visualizzazione della ricerca
  • Transizione Dissolvenza attraverso tra le pagine delle caselle di posta
  • Transizione di Container Transform dal chip di indirizzo email alla visualizzazione schede

Il dominio dell'iframe richiesto (youtu.be) non è stato autorizzato.

Che cosa ti serve

  • Conoscenza di base dello sviluppo Android e di Kotlin
  • Android Studio (scaricalo qui se non l'hai ancora fatto)
  • Un emulatore o un dispositivo Android (disponibile tramite Android Studio)
  • Il codice di esempio (vedi il passaggio successivo)

Come giudichi il tuo livello di esperienza nello sviluppo di app per Android?

Principiante Livello intermedio Eccellente

2. Configurazione dell'ambiente di sviluppo

Avvia Android Studio

Quando apri Android Studio, dovrebbe essere visualizzata una finestra chiamata "Ti diamo il benvenuto in Android Studio". Tuttavia, se è la prima volta che avvii Android Studio, segui la procedura della Configurazione guidata di Android Studio con i valori predefiniti. Questo passaggio può richiedere diversi minuti per scaricare e installare i file necessari, quindi non esitare a lasciarlo in esecuzione in background mentre esegui la prossima sezione.

Opzione 1: clona l'app codelab iniziale da GitHub

Per clonare questo codelab da GitHub, esegui questi comandi:

git clone https://github.com/material-components/material-components-android-motion-codelab.git
cd material-components-android-motion-codelab

Opzione 2: scarica il file ZIP dell'app codelab iniziale

L'app iniziale si trova nella directory material-components-android-motion-codelab-develop.

Carica il codice di avvio in Android Studio

  1. Al termine della configurazione guidata e visualizzata la finestra Ti diamo il benvenuto in Android Studio, fai clic su Apri un progetto Android Studio esistente.

e3f200327a67a53.png

  1. Passa alla directory in cui hai installato il codice di esempio e selezionala per aprire il progetto.
  2. Attendi un momento affinché Android Studio crei e sincronizzi il progetto, come mostrato dagli indicatori di attività nella parte inferiore della finestra di Android Studio.
  1. A questo punto, Android Studio potrebbe generare alcuni errori di generazione perché non disponi dell'SDK Android o degli strumenti di sviluppo, come quello mostrato di seguito. Segui le istruzioni in Android Studio per installarle/aggiornarle e sincronizzare il progetto. Se i problemi persistono, segui la guida sull'aggiornamento degli strumenti con SDK Manager.

6e026ae171f5b1eb.png

Verifica le dipendenze del progetto

Il progetto richiede una dipendenza dalla libreria MDC-Android. Nel codice campione che hai scaricato dovrebbe già essere presente questa dipendenza, ma per scoprirlo diamo un'occhiata alla configurazione.

Passa al file build.gradle del modulo app e assicurati che il blocco dependencies includa una dipendenza su MDC-Android:

implementation 'com.google.android.material:material:1.2.0'

Esegui l'app iniziale

  1. Assicurati che la configurazione della build a sinistra del dispositivo scelto sia app.
  2. Premi il pulsante Esegui / Riproduci verde per creare ed eseguire l'app.

24218d0a6ae25803.png

  1. Se tra i dispositivi disponibili è già elencato un dispositivo Android, nella finestra Seleziona la destinazione del deployment vai al passaggio 8. In caso contrario, fai clic su Crea nuovo dispositivo virtuale.
  2. Nella schermata Seleziona hardware, seleziona uno smartphone, ad esempio Pixel 3, quindi fai clic su Avanti.
  3. Nella schermata Immagine di sistema, seleziona una versione di Android recente, preferibilmente il livello API più elevato. Se non è installata, fai clic sul link Scarica visualizzato e completa il download.
  4. Fai clic su Avanti.
  5. Nella schermata Dispositivo virtuale Android, lascia le impostazioni invariate e fai clic su Fine.
  6. Seleziona un dispositivo Android dalla finestra di dialogo della destinazione dell'implementazione.
  7. Fai clic su Ok.
  8. Android Studio crea l'app, la distribuisce e la apre automaticamente sul dispositivo di destinazione.

Operazione riuscita. Il codice di avvio per la home page di Reply dovrebbe essere in esecuzione nell'emulatore. Dovresti vedere la Posta in arrivo contenente un elenco di email.

cc73eb0d0f779035.png

(Facoltativo) Rallentare le animazioni del dispositivo

Dal momento che questo codelab prevede transizioni rapide, ma molto raffinate, può essere utile rallentare le animazioni del dispositivo per osservare alcuni dettagli più minuti delle transizioni durante l'implementazione. A tale scopo, puoi usare i comandi della shell adb o un riquadro Impostazioni rapide. Tieni presente che questi metodi per rallentare le animazioni del dispositivo influiranno anche sul dispositivo al di fuori dell'app di risposta.

Metodo 1: comandi shell ADB

Per rallentare le animazioni del dispositivo di un fattore di 10 volte, puoi eseguire i seguenti comandi dalla riga di comando:

adb shell settings put global window_animation_scale 10
adb shell settings put global transition_animation_scale 10
adb shell settings put global animator_duration_scale 10

Per ripristinare la velocità di animazione normale del dispositivo, esegui i seguenti comandi:

adb shell settings put global window_animation_scale 1
adb shell settings put global transition_animation_scale 1
adb shell settings put global animator_duration_scale 1

Metodo 2: riquadro Impostazioni rapide

In alternativa, per configurare il riquadro Impostazioni rapide, abilita prima le Impostazioni sviluppatore sul tuo dispositivo se non l'hai ancora fatto:

  1. Apri "Impostazioni" sul dispositivo. app
  2. Scorri fino in fondo e fai clic su "Informazioni sul dispositivo emulato"
  3. Scorri fino in fondo e fai clic rapidamente su "Numero build". fino all'attivazione delle impostazioni sviluppatore

Quindi, svolgi le seguenti operazioni, sempre nelle "Impostazioni" del dispositivo per abilitare il riquadro Impostazioni rapide:

  1. Fai clic sull'icona di ricerca o sulla barra di ricerca nella parte superiore dello schermo.
  2. Digita "riquadri" nel campo di ricerca
  3. Fai clic sui "Riquadri sviluppatore Impostazioni rapide" riga
  4. Fai clic sulla "Scala dell'animazione finestra" passaggio

Infine, durante il codelab, trascina verso il basso l'area notifiche di sistema dalla parte superiore dello schermo e utilizza l'icona c7e3f98200023f6a.png per passare dalle animazioni a velocità normale a quella lenta.

3. Acquisisci familiarità con il codice dell'app di esempio

Diamo un'occhiata al codice. Abbiamo fornito un'app che utilizza la libreria del componente Navigazione Jetpack per navigare tra diversi Frammenti, il tutto all'interno di una singola attività, MainActivity:

  • HomeFragment:mostra un elenco di email
  • EmailFragment: visualizza una singola email completa
  • ComposeFragment:consente di comporre una nuova email.
  • SearchFragment: mostra una visualizzazione della ricerca

Innanzitutto, per capire come è configurato il grafico di navigazione dell'app, apri navigation_graph.xml nella directory app -> src -> main -> res -> navigation:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:id="@+id/navigation_graph"
   app:startDestination="@id/homeFragment">

   <fragment
       android:id="@+id/homeFragment"
       android:name="com.materialstudies.reply.ui.home.HomeFragment"
       android:label="HomeFragment">
       <argument...>
       <action
           android:id="@+id/action_homeFragment_to_emailFragment"
           app:destination="@id/emailFragment" />
   </fragment>
   <fragment
       android:id="@+id/emailFragment"
       android:name="com.materialstudies.reply.ui.email.EmailFragment"
       android:label="EmailFragment">
       <argument...>
   </fragment>
   <fragment
       android:id="@+id/composeFragment"
       android:name="com.materialstudies.reply.ui.compose.ComposeFragment"
       android:label="ComposeFragment">
       <argument...>
   </fragment>
   <fragment
       android:id="@+id/searchFragment"
       android:name="com.materialstudies.reply.ui.search.SearchFragment"
       android:label="SearchFragment" />
   <action
       android:id="@+id/action_global_homeFragment"
       app:destination="@+id/homeFragment"
       app:launchSingleTop="true"
       app:popUpTo="@+id/navigation_graph"
       app:popUpToInclusive="true"/>
   <action
       android:id="@+id/action_global_composeFragment"
       app:destination="@+id/composeFragment" />
   <action
       android:id="@+id/action_global_searchFragment"
       app:destination="@+id/searchFragment" />
</navigation>

Prendi nota di come sono presenti tutti i frammenti menzionati sopra, con il frammento di lancio predefinito impostato su HomeFragment tramite app:startDestination="@id/homeFragment". Questa definizione XML del grafico di destinazione del frammento, così come le azioni, informa il codice di navigazione Kotlin generato che incontrerai durante il collegamento delle transizioni.

activity_main.xml

Ora dai un'occhiata al layout activity_main.xml nella directory app -> src -> main -> res -> layout. Vedrai il NavHostFragment che è configurato con il grafico di navigazione in alto:

<fragment
   android:id="@+id/nav_host_fragment"
   android:name="androidx.navigation.fragment.NavHostFragment"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   app:defaultNavHost="true"
   app:navGraph="@navigation/navigation_graph"/>

Questo NavHostFragment riempie lo schermo e gestisce tutte le modifiche alla navigazione dei frammenti a schermo intero nell'app. Il BottomAppBar e il relativo FloatingActionButton ancorato, anch'esso in activity_main.xml, sono posizionati sopra il frammento corrente visualizzato da NavHostFragment e pertanto verranno mostrati o nascosti a seconda della destinazione del frammento dal codice dell'app di esempio fornito.

Inoltre, il BottomNavDrawerFragment in activity_main.xml è un riquadro a scomparsa in basso che contiene un menu per navigare tra le diverse caselle di posta email, che viene mostrato in modo condizionale tramite il pulsante con il logo Rispondi di BottomAppBar.

MainActivity.kt

Infine, per vedere un esempio di un'azione di navigazione in uso, apri MainActivity.kt nella directory app -> src -> main -> java -> com.materialstudies.reply.ui. Individua la funzione navigateToSearch(), che dovrebbe avere il seguente aspetto:

private fun navigateToSearch() {
   val directions = SearchFragmentDirections.actionGlobalSearchFragment()
   findNavController(R.id.nav_host_fragment).navigate(directions)
}

Questo mostra come raggiungere la pagina di visualizzazione della ricerca senza alcuna transizione personalizzata. Nel corso di questo codelab, analizzerai la MainActivity di Reply e quattro frammenti principali per configurare transizioni Material che funzionino in tandem con le varie azioni di navigazione nell'app.

Ora che hai acquisito familiarità con il codice di base, implementiamo la nostra prima transizione.

4. Aggiungi la transizione Container Transform dalla mailing list alla pagina dei dettagli dell'email

Per iniziare, aggiungerai una transizione quando fai clic su un'email. Per questa modifica alla navigazione, il pattern di trasformazione del container è adatto poiché è progettato per le transizioni tra elementi UI che includono un container. Questo pattern crea una connessione visibile tra due elementi UI.

Prima di aggiungere il codice, prova a eseguire l'app di risposta e a fare clic su un'email. Deve eseguire un semplice jump cut, che consente di sostituire lo schermo senza transizione:

f0e8a92eb2216bce.gif

Inizia aggiungendo un attributo transitionName in MaterialCardView in email_item_layout.xml, come mostrato nel seguente snippet:

email_item_layout.xml

android:transitionName="@{@string/email_card_transition_name(email.id)}"

Il nome della transizione include una risorsa stringa con un parametro. Devi utilizzare l'ID di ogni email per assicurarti che ogni transitionName nel nostro EmailFragment sia univoco.

Ora che hai impostato il nome della transizione dell'elemento della tua mailing list, ripetiamo la stessa operazione nel layout dei dettagli email. In fragment_email.xml, imposta transitionName di MaterialCardView sulla seguente risorsa stringa:

fragment_email.xml

android:transitionName="@string/email_card_detail_transition_name"

In HomeFragment.kt, sostituisci il codice in onEmailClicked con lo snippet riportato di seguito per creare la mappatura dalla vista iniziale (elemento dell'elenco email) e dalla vista finale (schermata dei dettagli email):

HomeFragment.kt

val emailCardDetailTransitionName = getString(R.string.email_card_detail_transition_name)
val extras = FragmentNavigatorExtras(cardView to emailCardDetailTransitionName)
val directions = HomeFragmentDirections.actionHomeFragmentToEmailFragment(email.id)
findNavController().navigate(directions, extras)

Ora che hai configurato l'impianto idraulico, puoi creare una trasformazione del container. Nel metodo onCreate EmailFragment, imposta sharedElementEnterTransition su una nuova istanza di MaterialContainerTransform (importando la versione com.google.android.material.transition anziché la versione com.google.android.material.transition.platform) aggiungendo il seguente snippet:

EmailFragment.kt

sharedElementEnterTransition = MaterialContainerTransform().apply {
   drawingViewId = R.id.nav_host_fragment
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   scrimColor = Color.TRANSPARENT
   setAllContainerColors(requireContext().themeColor(R.attr.colorSurface))
}

Ora prova a eseguire di nuovo l'app.

ed62cedec31da268.gif

Tutto inizia a essere bello! Quando fai clic su un'email nella mailing list, una trasformazione del contenitore dovrebbe espandere l'elemento dell'elenco in una pagina dei dettagli a schermo intero. Nota, però, che premendo Indietro l'email non viene compressa nuovamente nell'elenco. Inoltre, la mailing list scompare immediatamente all'inizio della transizione e viene mostrato lo sfondo grigio della finestra. Quindi non abbiamo ancora finito.

Per correggere la transizione di ritorno, aggiungi le due righe seguenti al metodo onViewCreated in HomeFragment.kt:

HomeFragment.kt

postponeEnterTransition()
view.doOnPreDraw { startPostponedEnterTransition() }

Prova a eseguire di nuovo l'app. Se premi Indietro dopo l'apertura di un'email, l'email verrà compressa di nuovo nell'elenco. Bene! Continuiamo a migliorare l'animazione.

Il problema della scomparsa della mailing list è che, quando accedi a un nuovo Frammento utilizzando il componente di navigazione, il frammento corrente viene immediatamente rimosso e sostituito con il nostro nuovo Frammento in arrivo. Per mantenere visibile la mailing list anche dopo la sostituzione, puoi aggiungere una transizione di uscita a HomeFragment.

Aggiungi lo snippet seguente al metodo HomeFragment onEmailClicked per fare in modo che l'elenco delle email venga ridotto leggermente all'uscita e viceversa:

HomeFragment.kt

exitTransition = MaterialElevationScale(false).apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
reenterTransition = MaterialElevationScale(true).apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}

Successivamente, per assicurarti che la transizione MaterialElevationScale venga applicata alla schermata Home nel suo complesso, anziché a ogni singola visualizzazione della gerarchia, contrassegna RecyclerView in fragment_home.xml come gruppo di transizione.

fragment_home.xml

android:transitionGroup="true"

In questa fase, dovresti avere una trasformazione del container completamente funzionante. Se fai clic su un'email, l'elemento dell'elenco si espande in una schermata dei dettagli, mentre restringi l'elenco di email. Se si preme Indietro, la schermata dei dettagli dell'email torna a essere visualizzata nell'elenco mentre viene fatto lo scale up nell'elenco delle email.

9df2b39d5a150418.gif

5. Aggiungi la transizione Container Transform da FAB alla pagina di scrittura delle email

Continuiamo con la trasformazione del container e aggiungiamo una transizione dal pulsante di azione mobile a ComposeFragment, espandendo il FAB a una nuova email che l'utente deve scrivere. Innanzitutto, esegui di nuovo l'app e fai clic sul FAB per vedere che non ci sono transizioni all'avvio della schermata di scrittura dell'email.

d242c9708abd382c.gif

Anche se utilizziamo la stessa classe di transizione, il modo in cui configuriamo questa istanza sarà diverso perché il nostro FAB si trova in MainActivity e il nostro ComposeFragment è posizionato all'interno del container host di navigazione MainActivity.

In ComposeFragment.kt, aggiungi il seguente snippet al metodo onViewCreated, assicurandoti di importare la versione androidx.transition di Slide.

ComposeFragment.kt

enterTransition = MaterialContainerTransform().apply {
   startView = requireActivity().findViewById(R.id.fab)
   endView = emailCardView
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   scrimColor = Color.TRANSPARENT
   containerColor = requireContext().themeColor(R.attr.colorSurface)
   startContainerColor = requireContext().themeColor(R.attr.colorSecondary)
   endContainerColor = requireContext().themeColor(R.attr.colorSurface)
}
returnTransition = Slide().apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_medium).toLong()
   addTarget(R.id.email_card_view)
}

Oltre ai parametri utilizzati per configurare la precedente trasformazione del container, startView e endView vengono impostati manualmente qui. Anziché utilizzare gli attributi transitionName per indicare al sistema di transizione Android quali viste devono essere trasformate, puoi specificarle manualmente quando necessario.

Ora esegui di nuovo l'app. Dovresti vedere il FAB che si trasforma nella schermata di composizione (vedi la GIF alla fine di questo passaggio).

Come nel passaggio precedente, devi aggiungere una transizione a HomeFragment per evitare che scompaia dopo essere stato rimosso e sostituito con ComposeFragment.

Copia lo snippet riportato di seguito nel metodo navigateToCompose in MainActivity prima della chiamata NavController navigate.

MainActivity.kt

currentNavigationFragment?.apply {
   exitTransition = MaterialElevationScale(false).apply {
       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
   reenterTransition = MaterialElevationScale(true).apply {
       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
}

Questo è tutto. Dovresti avere una transizione dal FAB per creare una schermata di composizione simile alla seguente:

81b68391ac4b0a9.gif

6. Aggiungi la transizione sull'asse Z condivisa dall'icona di ricerca alla pagina di visualizzazione della ricerca

In questo passaggio, aggiungeremo una transizione dall'icona di ricerca alla visualizzazione della ricerca a schermo intero. Poiché questa modifica alla navigazione non prevede un container permanente, possiamo utilizzare una transizione sull'asse Z condiviso per rafforzare la relazione spaziale tra le due schermate e indicare lo spostamento di un livello verso l'alto nella gerarchia dell'app.

Prima di aggiungere altro codice, prova a eseguire l'app e a toccare l'icona di ricerca nell'angolo in basso a destra dello schermo. Dovrebbe apparire la schermata di visualizzazione della ricerca senza transizione.

499e1a677b4216bb.gif

Per iniziare, trova il metodo navigateToSearch in MainActivity e aggiungi il seguente snippet di codice prima della chiamata al metodo navigate NavController per configurare l'uscita del frammento corrente e reinserire MaterialSharedAxis transizioni sull'asse Z.

MainActivity.kt

currentNavigationFragment?.apply {
   exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).apply {
       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
   reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false).apply {
       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
}

Successivamente, aggiungi il seguente snippet di codice al metodo onCreate in SearchFragment, che configura le transizioni Invio e Restituisci MaterialSharedAxis.

SearchFragment.kt

enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false).apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}

Infine, per assicurarti che la transizione MaterialSharedAxis venga applicata alla schermata di ricerca nel suo complesso, invece che a ogni singola visualizzazione della gerarchia, contrassegna LinearLayout in fragment_search.xml come gruppo di transizione.

fragment_search.xml

android:transitionGroup="true"

È tutto. Ora prova a eseguire di nuovo l'app e a toccare l'icona di ricerca. Le schermate Home e Ricerca devono contemporaneamente sfocare e ridimensionare in profondità l'asse Z, creando un effetto omogeneo tra le due schermate.

e5c0b0a130e807db.gif

7. Aggiungi una transizione Fade-through tra le pagine delle caselle di posta

In questo passaggio aggiungeremo una transizione tra diverse caselle di posta. Poiché non vogliamo enfatizzare una relazione spaziale o gerarchica, utilizzeremo una dissolvenza attraverso per eseguire un semplice "swap" tra gli elenchi di email.

Prima di aggiungere altro codice, prova a eseguire l'app, a toccare il logo Rispondi nella barra delle app in basso e a cambiare casella di posta. L'elenco delle email dovrebbe cambiare senza transizione.

2c874c0a4588e8fb.gif

Per iniziare, trova il metodo navigateToHome in MainActivity e aggiungi il seguente snippet di codice prima della chiamata al metodo navigate NavController per impostare la transizione MaterialFadeThrough di uscita del frammento corrente.

MainActivity.kt

currentNavigationFragment?.apply {
   exitTransition = MaterialFadeThrough().apply {
       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
}

Dopodiché apri HomeFragment. In onCreate, imposta il valore enterTransition del frammento su una nuova istanza di MaterialFadeThrough.

HomeFragment.kt

enterTransition = MaterialFadeThrough().apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}

Esegui di nuovo l'app. Quando apri il riquadro di navigazione a scomparsa in basso e cambi le caselle di posta, l'elenco corrente di email dovrebbe scomparire e fare lo scale out, mentre il nuovo elenco appare in dissolvenza e viene scalato. Bene!

f61dfd58ea7bd3fd.gif

8. Aggiungi la transizione Container Transform dal chip dell'indirizzo email alla visualizzazione schede

In questo passaggio, aggiungerai una transizione che trasforma un chip in una scheda popup. Qui viene utilizzata una trasformazione del contenitore per informare l'utente che l'azione intrapresa nel popup influirà sul chip da cui ha avuto origine il popup.

Prima di aggiungere codice, esegui l'app di risposta, fai clic su un'email, fai clic sulla risposta FAB, quindi prova a fare clic sul chip di contatto di un destinatario. Il chip dovrebbe scomparire immediatamente e dovrebbe apparire una scheda con gli indirizzi email di quel contatto, senza animazioni.

6200c682da2382d5.gif

Lavorerai in ComposeFragment per questo passaggio. Nel layout ComposeFragment sono già stati aggiunti i chip dei destinatari (visibili per impostazione predefinita) e una scheda del destinatario (invisibili per impostazione predefinita). Un chip destinatario e questa scheda sono le due visualizzazioni tra le quali creerai una trasformazione contenitore.

Per iniziare, apri ComposeFragment e trova il metodo expandChip. Questo metodo viene chiamato quando l'utente fa clic sull'elemento chip fornito. Aggiungi il seguente snippet di codice sopra le righe che scambiano la visibilità recipientCardView e chip, che attiverà la trasformazione del container registrata tramite beginDelayedTransition.

ComposeFragment.kt

val transform = MaterialContainerTransform().apply {
   startView = chip
   endView = binding.recipientCardView
   scrimColor = Color.TRANSPARENT
   endElevation = requireContext().resources.getDimension(
       R.dimen.email_recipient_card_popup_elevation_compat
   )
   addTarget(binding.recipientCardView)
}

TransitionManager.beginDelayedTransition(binding.composeConstraintLayout, transform)

Se esegui l'app ora, il chip dovrebbe trasformarsi in una scheda di indirizzi email per il destinatario. A questo punto configuriamo la transizione di ritorno per comprimere di nuovo la scheda nel chip.

Nel metodo collapseChip in ComposeFragment, aggiungi lo snippet di codice riportato di seguito per comprimere la scheda nel chip.

ComposeFragment.kt

val transform = MaterialContainerTransform().apply {
   startView = binding.recipientCardView
   endView = chip
   scrimColor = Color.TRANSPARENT
   startElevation = requireContext().resources.getDimension(
       R.dimen.email_recipient_card_popup_elevation_compat
   )
   addTarget(chip)
}

TransitionManager.beginDelayedTransition(binding.composeConstraintLayout, transform)

Esegui di nuovo l'app. Se fai clic sul chip, il chip dovrebbe espanderlo in una scheda, mentre se fai clic sulla scheda la scheda verrà compressa di nuovo all'interno del chip. Bene!

e823b28e2890e05d.gif

9. Fine

Utilizzando meno di 100 righe di codice Kotlin e un markup XML di base, la libreria MDC-Android ti ha aiutato a creare bellissime transizioni in un'app esistente conforme alle linee guida di Material Design, oltre che avere un aspetto e un comportamento coerenti su tutti i dispositivi Android.

454a47ba96017a25.gif

Passaggi successivi

Per ulteriori informazioni sul sistema di movimento Material, assicurati di consultare le specifiche e la documentazione completa per gli sviluppatori, quindi prova ad aggiungere alcune transizioni Material alla tua app.

Grazie per aver provato Material motion. Speriamo che questo codelab ti sia piaciuto.

Ho completato questo codelab con una quantità di tempo e di sforzi ragionevoli

Totalmente d'accordo D'accordo Né chiara, né confusa In disaccordo Totalmente in disaccordo

Vorrei continuare a usare il sistema di movimento Material in futuro

Totalmente d'accordo D'accordo Né chiara, né confusa In disaccordo Totalmente in disaccordo