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

Che cos'è il sistema di movimento di Material per Android?

Il sistema di movimento Material per Android è un insieme di pattern di transizione all'interno della libreria MDC-Android che può 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 del contenitore: transizioni tra elementi dell'interfaccia utente che includono un contenitore. Crea un collegamento visibile tra due elementi dell'interfaccia utente distinti trasformando facilmente un elemento in un altro.
  • Asse condiviso: transizioni tra elementi dell'interfaccia utente che hanno una relazione spaziale o di navigazione; utilizza una trasformazione condivisa sull'asse x, y o z per rafforzare la relazione tra gli elementi.
  • Dissolvenza tramite: transizioni tra elementi dell'interfaccia utente che non hanno una forte correlazione tra loro. Utilizza una dissolvenza in entrata e in uscita sequenziale, con una scala dell'elemento in entrata.
  • Dissolvenza: utilizzata per gli elementi dell'interfaccia utente che entrano o escono dalle estremità della schermata.

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

AndroidX

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

Framework

  • Disponibile nel pacchetto com.google.android.material.transition.platform
  • Supporta il livello API 21 e versioni successive
  • Supporta frammenti, viste, attività e finestre
  • Le correzioni di bug non sono state sottoposte a backporting e potrebbero avere un comportamento diverso nei vari livelli API

In questo codelab utilizzerai le transizioni Material create sulla base della 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 di posta elettronica Android di esempio chiamata Rispondi, utilizzando Kotlin, per dimostrare come puoi utilizzare le transizioni della libreria MDC-Android per personalizzare l'aspetto della tua app.

Ti verrà fornito il codice di avvio dell'app Reply e dovrai incorporare le seguenti transizioni Material nell'app, che puoi vedere nella GIF del codelab completato di seguito:

  • 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 dell'asse Z condivisa dall'icona di ricerca alla pagina di visualizzazione della ricerca
  • Transizione Dissolvenza tra le pagine della casella di posta
  • Transizione di Container Transform dal chip dell'indirizzo email alla visualizzazione scheda

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 lo hai già)
  • Un emulatore o un dispositivo Android (disponibile tramite Android Studio)
  • Il codice di esempio (vedi il passaggio successivo)

Come valuteresti il tuo livello di esperienza nella creazione di app per Android?

Principiante Livello intermedio Livello avanzato

2. Configurazione dell'ambiente di sviluppo

Avvia Android Studio

Quando apri Android Studio, dovrebbe essere visualizzata la finestra "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 del codelab di avvio

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 viene 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 per consentire ad Android Studio di compilare e sincronizzare il progetto, come indicato dagli indicatori di attività nella parte inferiore della finestra di Android Studio.
  1. A questo punto, Android Studio potrebbe segnalare alcuni errori di compilazione perché mancano gli strumenti di compilazione o l'SDK Android, come quello mostrato di seguito. Segui le istruzioni in Android Studio per installare/aggiornare questi componenti 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. Il codice di esempio che hai scaricato dovrebbe già avere questa dipendenza elencata, ma diamo un'occhiata alla configurazione per assicurarci.

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

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

Esegui l'app iniziale

  1. Assicurati che la configurazione di compilazione a sinistra della scelta del dispositivo 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 è installato, 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 Destinazione di deployment.
  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

Poiché questo codelab prevede transizioni rapide, ma raffinate, può essere utile rallentare le animazioni del dispositivo per osservare alcuni dei dettagli più fini 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 sulle animazioni del dispositivo al di fuori dell'app Reply.

Metodo 1: comandi shell ADB

Per rallentare le animazioni del dispositivo 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 l'app "Impostazioni" del dispositivo.
  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" finché non vengono attivate le Impostazioni sviluppatore

Per attivare il riquadro delle Impostazioni rapide, procedi nel seguente modo, sempre all'interno dell'app "Impostazioni" del dispositivo:

  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 sulla riga "Riquadri sviluppatore per le Impostazioni rapide".
  4. Fai clic sull'opzione "Scala animazione finestra"

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: mostra un'unica email completa
  • ComposeFragment: consente la composizione di una nuova email
  • SearchFragment: mostra una visualizzazione della ricerca

Innanzitutto, per capire come è configurato il grafo 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>

Tieni presente che tutti i frammenti sopra menzionati sono presenti, 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 NavHostFragment configurato con il grafico di navigazione dall'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 relative alla navigazione dei frammenti a schermo intero nell'app. Il BottomAppBar e i suoi FloatingActionButton ancorati, anch'essi 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 puoi passare alla pagina della 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. Aggiungere la transizione di Container Transform dall'elenco email 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 in quanto è progettato per le transizioni tra elementi UI che includono un container. Questo pattern crea una connessione visibile tra due elementi UI.

Prima di aggiungere qualsiasi codice, prova a eseguire l'app Rispondi e fai 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 accetta 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 di transizione dell'elemento dell'elenco email, fai lo stesso nel layout dei dettagli dell'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 seguente per creare la mappatura dalla visualizzazione iniziale (elemento dell'elenco di email) e dalla visualizzazione finale (schermata dei dettagli dell'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

Sembra che tutto stia andando per il meglio. Quando fai clic su un'email nell'elenco, una trasformazione del contenitore dovrebbe espandere l'elemento dell'elenco in una pagina dei dettagli a schermo intero. Tuttavia, tieni presente che premendo Indietro l'email non viene compressa di nuovo nell'elenco. Inoltre, l'elenco di email scompare immediatamente all'inizio della transizione, mostrando 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 aver aperto un'email, l'email verrà compressa di nuovo nell'elenco. Bene! Continuiamo a migliorare l'animazione.

Il problema della scomparsa dell'elenco di email si verifica perché, quando si passa a un nuovo frammento utilizzando il componente di navigazione, il frammento corrente viene immediatamente rimosso e sostituito dal 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 e l'elenco delle email si riduce. 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 contenitore e aggiungiamo una transizione dal pulsante di azione mobile a ComposeFragment, espandendo il pulsante di azione mobile in una nuova email da scrivere dall'utente. Innanzitutto, esegui di nuovo l'app e fai clic sul FAB per verificare che non ci sia alcuna transizione quando viene lanciata la schermata di composizione dell'email.

d242c9708abd382c.gif

Sebbene utilizziamo lo stesso metodo di transizione, il modo in cui configuriamo questa istanza sarà diverso poiché il nostro FAB si trova in MainActivity e il nostro ComposeFragment è inserito all'interno del contenitore 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 trasformazione del contenitore precedente, 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 da 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 per questo passaggio. Dovresti avere una transizione dal pulsante FAB alla schermata di composizione simile alla seguente:

81b68391ac4b0a9.gif

6. Aggiungi la transizione dell'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é in questa modifica della navigazione non è coinvolto alcun contenitore persistente, possiamo utilizzare una transizione sull'asse Z condiviso per rafforzare la relazione spaziale tra le due schermate e indicare il passaggio a un livello superiore nella gerarchia dell'app.

Prima di aggiungere altro codice, prova a eseguire l'app e tocca 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()
   }
}

Aggiungi quindi il seguente snippet di codice al metodo onCreate in SearchFragment, che configura le transizioni MaterialSharedAxis di entrata e ritorno.

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, anziché a ciascuna delle singole visualizzazioni nella 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. Aggiungere la transizione Dissolvenza tra le pagine della cassetta postale

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

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

2c874c0a4588e8fb.gif

Per iniziare, trova il metodo navigateToHome in MainActivity e aggiungi il seguente snippet di codice prima della chiamata al metodo NavController navigate per configurare 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()
   }
}

Poi 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 in basso e cambi casella di posta, l'elenco corrente delle email dovrebbe svanire e rimpicciolirsi, mentre il nuovo elenco dovrebbe svanire e ingrandirsi. 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 qualsiasi codice, esegui l'app Rispondi, fai clic su un'email, fai clic sul pulsante FAB "Rispondi" e poi prova a fare clic sul chip contatto di un destinatario. Il chip dovrebbe scomparire immediatamente e una scheda con gli indirizzi email del contatto dovrebbe apparire 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 carta 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à di recipientCardView e chip, che attiverà la trasformazione del contenitore 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, questo dovrebbe espandersi in una scheda, mentre se fai clic sulla scheda, questa dovrebbe richiudersi nel 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, consulta le specifiche e la documentazione completa per gli sviluppatori e 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 Neutrale In disaccordo Totalmente in disaccordo

Vorrei continuare a usare il sistema di movimento Material in futuro

Molto d'accordo D'accordo Né d'accordo né in disaccordo In disaccordo Totalmente in disaccordo