Mit Material Motion für Android schöne Übergänge erstellen

1. Einführung

Material Design ist ein System zum Erstellen ausdrucksstarker und ansprechender digitaler Produkte. Wenn Produktteams Stil, Branding, Interaktion und Bewegung in einer einheitlichen Reihe von Prinzipien und Komponenten vereinen, können sie ihr volles Designpotenzial ausschöpfen.

logo_components_color_2x_web_96dp.png

Mit Material Components (MDC) können Entwickler Material Design implementieren. MDC wurde von einem Team aus Entwicklern und UX-Designern bei Google entwickelt. Es enthält Dutzende schöne und funktionale UI-Komponenten und ist für Android, iOS, das Web und Flutter.material.io/develop verfügbar.

Was ist das Bewegungssystem von Material für Android?

Das Material-Bewegungssystem für Android besteht aus einer Reihe von Übergangsmustern innerhalb der MDC-Android-Bibliothek, die Nutzern helfen können, eine App zu verstehen und sich darin zurechtzufinden. Eine Beschreibung hierzu finden Sie in den Material Design-Richtlinien.

Die vier Hauptmuster für Materialübergänge sind:

  • Container Transform:Übergänge zwischen UI-Elementen, die einen Container enthalten; stellt eine sichtbare Verbindung zwischen zwei verschiedenen UI-Elementen her, indem ein Element nahtlos in ein anderes umgewandelt wird.
  • Gemeinsam genutzte Achse:Übergänge zwischen UI-Elementen, die eine räumliche oder Navigationsbeziehung haben. Es wird eine gemeinsame Transformation auf der X-, Y- oder Z-Achse verwendet, um die Beziehung zwischen den Elementen zu verstärken.
  • Durchblenden: Übergänge zwischen UI-Elementen, die nicht stark miteinander verbunden sind. Es wird ein sequenzielles Aus- und Einblenden mit einer Skalierung des eingehenden Elements verwendet.
  • Überblenden: Wird für UI-Elemente verwendet, die innerhalb der Bildschirmgrenzen ein- oder ausgeblendet werden.

Die MDC-Android-Bibliothek bietet Übergänge für diese Muster, die auf der AndroidX Transition Library (androidx.transition) und dem Android Transition Framework (android.transition) basieren:

AndroidX

  • Im Paket com.google.android.material.transition verfügbar
  • Unterstützt API-Level 14 und höher
  • Unterstützt Fragmente und Ansichten, aber keine Aktivitäten oder Windows
  • Enthält zurückportierte Fehlerkorrekturen und konsistentes Verhalten auf allen API-Levels

Framework

  • Verfügbar im com.google.android.material.transition.platform-Paket
  • Unterstützt API-Level 21 oder höher
  • Unterstützt Fragmente, Datenansichten, Aktivitäten und Zeiträume
  • Fehlerkorrekturen werden nicht zurückportiert und können sich auf verschiedenen API-Ebenen unterschiedlich verhalten

In diesem Codelab verwenden Sie die Material-Übergänge, die auf der AndroidX-Bibliothek basieren. Sie konzentrieren sich also hauptsächlich auf Fragmente und Ansichten.

Inhalt

In diesem Codelab erfahren Sie, wie Sie mithilfe von Kotlin einige Übergänge zu einer Android-E-Mail-App namens Reply erstellen und zeigen, wie Sie mit Übergängen aus der MDC-Android-Bibliothek das Design Ihrer App anpassen können.

Der Startcode für die Antwort-App wird bereitgestellt und du integrierst die folgenden Materialübergänge in die App, die im fertigen Codelab im GIF unten zu sehen sind:

  • Container Transform: Übergang von der E-Mail-Liste zur E-Mail-Detailseite
  • Container Transform: Wechsel von der FAB zur Seite zum Verfassen von E-Mails
  • Gemeinsam genutzte Z-Achse: Übergang vom Suchsymbol zur Suchansicht
  • Wechsel per Überblendung zwischen Postfachseiten
  • Container Transform: Wechsel vom E-Mail-Adressen-Chip zur Kartenansicht

Die Domain des angeforderten Iframes (youtu.be) wurde nicht auf die Zulassungsliste gesetzt.

Voraussetzungen

  • Grundkenntnisse in Android-Entwicklung und Kotlin
  • Android Studio (hier herunterladen, falls Sie es noch nicht haben)
  • Ein Android-Emulator oder -Gerät (verfügbar über Android Studio)
  • Beispielcode (siehe nächster Schritt)

Wie würdest du deine Erfahrung mit der Entwicklung von Android-Apps bewerten?

Neuling Mittel Kompetent

2. Entwicklungsumgebung einrichten

Starten Sie Android Studio.

Wenn Sie Android Studio öffnen, sollte ein Fenster mit dem Titel „Welcome to Android Studio“ (Willkommen bei Android Studio) angezeigt werden. Wenn Sie Android Studio jedoch zum ersten Mal starten, führen Sie die Schritte im Android Studio-Einrichtungsassistenten mit den Standardwerten aus. Es kann einige Minuten dauern, bis die erforderlichen Dateien heruntergeladen und installiert wurden. Sie können diesen Schritt also im Hintergrund ausführen, während Sie mit dem nächsten Abschnitt fortfahren.

Option 1: Codelab-Anwendung für den Einstieg aus GitHub klonen

Führen Sie die folgenden Befehle aus, um dieses Codelab aus GitHub zu klonen:

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

Option 2: ZIP-Datei der Codelab-Starter-App herunterladen

Die Starter-App befindet sich im Verzeichnis material-components-android-motion-codelab-develop.

Startcode in Android Studio laden

  1. Wenn der Einrichtungsassistent abgeschlossen ist und das Fenster Willkommen bei Android Studio angezeigt wird, klicken Sie auf Bestehendes Android Studio-Projekt öffnen.

e3f200327a67a53.png

  1. Rufen Sie das Verzeichnis auf, in dem Sie den Beispielcode installiert haben, und wählen Sie das Beispielverzeichnis aus, um das Projekt zu öffnen.
  2. Warten Sie einen Moment, bis Android Studio das Projekt erstellt und synchronisiert hat. Das wird durch Aktivitätssymbole am unteren Rand des Android Studio-Fensters angezeigt.
  1. An dieser Stelle meldet Android Studio möglicherweise einige Buildfehler, weil das Android SDK oder die Buildtools fehlen, z. B. den unten gezeigten. Folgen Sie der Anleitung in Android Studio, um diese zu installieren bzw. zu aktualisieren und Ihr Projekt zu synchronisieren. Sollten weiterhin Probleme auftreten, folge der Anleitung zum Aktualisieren deiner Tools mit dem SDK-Manager.

6e026ae171f5b1eb.png

Projektabhängigkeiten prüfen

Das Projekt benötigt eine Abhängigkeit von der MDC-Android-Bibliothek. Diese Abhängigkeit sollte bereits im heruntergeladenen Beispielcode aufgeführt sein. Sehen wir uns die Konfiguration an, um sicherzugehen.

Gehen Sie zur Datei build.gradle des Moduls app und achten Sie darauf, dass der Block dependencies eine Abhängigkeit von MDC-Android enthält:

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

Start-App ausführen

  1. Achten Sie darauf, dass die Build-Konfiguration links neben dem Gerät app lautet.
  2. Drücken Sie die grüne Schaltfläche Ausführen/Wiedergeben, um die App zu erstellen und auszuführen.

24218d0a6ae25803.png

  1. Wenn im Fenster Bereitstellungsziel auswählen bereits ein Android-Gerät in den verfügbaren Geräten aufgeführt ist, fahren Sie mit Schritt 8 fort. Klicken Sie andernfalls auf Neues virtuelles Gerät erstellen.
  2. Wählen Sie auf dem Bildschirm Hardware auswählen ein Smartphone wie Pixel 3 aus und klicken Sie auf Weiter.
  3. Wählen Sie auf dem Bildschirm System-Image eine neuere Android-Version aus, vorzugsweise die höchste API-Ebene. Falls sie nicht installiert ist, klicken Sie auf den angezeigten Link Herunterladen und schließen Sie den Download ab.
  4. Klicken Sie auf Weiter.
  5. Lassen Sie auf dem Bildschirm Android Virtual Device (AVD) die Einstellungen unverändert und klicken Sie auf Fertigstellen.
  6. Wählen Sie im Dialogfeld für das Bereitstellungsziel ein Android-Gerät aus.
  7. Klicken Sie auf OK.
  8. Android Studio erstellt die App, stellt sie bereit und öffnet sie automatisch auf dem Zielgerät.

Fertig! Der Starter-Code für die Reply-Startseite sollte in deinem Emulator ausgeführt werden. Sie sollten den Posteingang mit einer Liste von E-Mails sehen.

cc73eb0d0f779035.png

Optional: Geräteanimationen verlangsamen

Da dieses Codelab schnelle, aber ausgefeilte Übergänge beinhaltet, kann es hilfreich sein, die Animationen des Geräts zu verlangsamen, um bei der Implementierung einige der feineren Details der Übergänge zu beobachten. Das ist entweder mit adb-Shell-Befehlen oder einer Kachel für Schnelleinstellungen möglich. Hinweis: Diese Methoden zur Verlangsamung von Geräteanimationen wirken sich auch auf Animationen auf dem Gerät außerhalb der Reply App aus.

Methode 1: ADB-Shell-Befehle

Wenn Sie die Animationen des Geräts um das Zehnfache verlangsamen möchten, können Sie die folgenden Befehle in der Befehlszeile ausführen:

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

Führen Sie die folgenden Befehle aus, um die Animationsgeschwindigkeit des Geräts auf die normale Geschwindigkeit zurückzusetzen:

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

Methode 2: Kachel „Schnelleinstellungen“

Alternativ kannst du zum Einrichten der Schnelleinstellungskachel zuerst die Entwicklereinstellungen auf deinem Gerät aktivieren, falls du dies noch nicht getan hast:

  1. Öffnen Sie die Einstellungen auf Ihrem Gerät.
  2. Scrollen Sie nach unten und klicken Sie auf „Informationen zum emulierten Gerät“.
  3. Scrollen Sie nach unten und klicken Sie mehrmals auf „Build-Nummer“, bis die Entwicklereinstellungen aktiviert sind.

Führen Sie als Nächstes in den Einstellungen des Geräts die folgenden Schritte aus, um die Kachel „Schnelleinstellungen“ zu aktivieren:

  1. Klicken Sie oben auf dem Bildschirm auf das Suchsymbol oder die Suchleiste.
  2. Geben Sie „tiles“ in das Suchfeld ein.
  3. Klicken Sie auf die Zeile „Entwicklerkacheln für Schnelleinstellungen“.
  4. Klicken Sie auf den Schalter „Fensteranimationsskalierung“.

Ziehen Sie schließlich im Codelab die Systembenachrichtigungsleiste vom oberen Bildschirmrand nach unten und verwenden Sie das c7e3f98200023f6a.png-Symbol, um zwischen Animationen mit langsamer und normaler Geschwindigkeit zu wechseln.

3. Mit dem Beispielcode der App vertraut machen

Sehen wir uns den Code an. Wir stellen Ihnen eine App zur Verfügung, die die Komponente „Jetpack Navigation“ verwendet, um zwischen verschiedenen Fragmenten innerhalb einer einzigen Aktivität, MainActivity zu navigieren:

  • HomeFragment:Eine Liste von E-Mail-Adressen wird angezeigt.
  • EmailFragment: Hier wird eine einzelne vollständige E-Mail angezeigt.
  • ComposeFragment: Ermöglicht das Verfassen einer neuen E-Mail.
  • SearchFragment:Zeigt eine Suchansicht an

Wenn Sie wissen möchten, wie das Navigationsdiagramm der App aufgebaut ist, öffnen Sie navigation_graph.xml im Verzeichnis 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>

Beachten Sie, dass alle oben genannten Fragmente vorhanden sind und das Standard-Startfragment auf HomeFragment über app:startDestination="@id/homeFragment" festgelegt ist. Diese XML-Definition der Fragment-Zielgrafik sowie der Aktionen legen den generierten Kotlin-Navigationscode fest, dem Sie beim Hooking von Übergängen begegnen.

activity_main.xml

Sehen Sie sich als Nächstes das Layout activity_main.xml im Verzeichnis app -> src -> main -> res -> layout an. Sie sehen die NavHostFragment, die mit dem Navigationsdiagramm oben konfiguriert ist:

<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"/>

Diese NavHostFragment füllt den Bildschirm aus und verarbeitet alle Änderungen der Navigation im Vollbildfragment in der App. Die BottomAppBar und ihre verankerte FloatingActionButton, ebenfalls in activity_main.xml, werden über dem aktuellen Fragment angeordnet, das von der NavHostFragment angezeigt wird. Sie werden daher je nach Fragmentziel im bereitgestellten Beispiel-App-Code angezeigt oder ausgeblendet.

Außerdem ist das BottomNavDrawerFragment in activity_main.xml ein Drop-down-Menü, das sich unten befindet und mit dem Sie zwischen den verschiedenen E-Mail-Posteingängen wechseln können. Es wird bedingt über die Schaltfläche mit dem BottomAppBar-Logo für Antworten angezeigt.

MainActivity.kt

Wenn Sie sich ein Beispiel für eine Navigationsaktion ansehen möchten, öffnen Sie MainActivity.kt im Verzeichnis app -> src -> main -> java -> com.materialstudies.reply.ui. Suchen Sie die Funktion navigateToSearch(). Sie sollte so aussehen:

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

Hier sehen Sie, wie Sie ohne benutzerdefinierten Wechsel zur Suchansichtsseite navigieren können. In diesem Codelab lernen Sie die MainActivity von Reply und vier Hauptfragmente kennen, um Materialübergänge einzurichten, die mit den verschiedenen Navigationsaktionen in der App zusammenarbeiten.

Nachdem Sie sich mit dem Startcode vertraut gemacht haben, implementieren wir jetzt unsere erste Überleitung.

4. Container Transform-Umstellung von der E-Mail-Liste auf die E-Mail-Detailseite hinzufügen

Als Erstes fügen Sie einen Übergang hinzu, wenn Sie auf eine E-Mail klicken. Für diese Navigationsänderung eignet sich das Containertransformationsmuster gut, da es für Übergänge zwischen UI-Elementen vorgesehen ist, die einen Container enthalten. Dieses Muster schafft eine sichtbare Verbindung zwischen zwei UI-Elementen.

Bevor Sie Code hinzufügen, starten Sie die Reply App und klicken Sie auf eine E-Mail. Es sollte ein einfacher Jump Cut sein, d. h., der Bildschirm wird ohne Übergang ersetzt:

f0e8a92eb2216bce.gif

Fügen Sie zuerst ein transitionName-Attribut zum MaterialCardView in email_item_layout.xml hinzu, wie im folgenden Snippet gezeigt:

email_item_layout.xml

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

Der Übergangsname nimmt eine Stringressource mit einem Parameter an. Sie müssen die ID jeder E-Mail-Adresse verwenden, damit jeder transitionName in unserem EmailFragment eindeutig ist.

Nachdem Sie nun den Übergangsnamen für Ihr E-Mail-Listenelement festgelegt haben, können Sie im Layout der E-Mail-Details die gleichen Schritte durchführen. Legen Sie in fragment_email.xml die transitionName der MaterialCardView auf die folgende Stringressource fest:

fragment_email.xml

android:transitionName="@string/email_card_detail_transition_name"

Ersetzen Sie in HomeFragment.kt den Code in onEmailClicked durch das folgende Snippet, um die Zuordnung von der Startansicht (Element in der E-Mail-Liste) und von der Endansicht (Bildschirm mit E-Mail-Details) aus zu erstellen:

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)

Nachdem Sie die Verkabelung konfiguriert haben, können Sie eine Containertransformation erstellen. Legen Sie in der EmailFragment onCreate-Methode sharedElementEnterTransition auf eine neue Instanz einer MaterialContainerTransform fest (com.google.android.material.transition-Version statt com.google.android.material.transition.platform-Version importieren). Fügen Sie dazu das folgende Snippet hinzu:

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))
}

Versuchen Sie jetzt noch einmal, die App auszuführen.

ed62cedec31da268.gif

Es sieht schon gut aus! Wenn Sie auf eine E-Mail in der E-Mail-Liste klicken, sollte das Listenelement bei einer Containertransformation zu einer Detailseite im Vollbildmodus erweitert werden. Beachten Sie jedoch, dass die E-Mail durch Drücken der Rücktaste nicht wieder in die Liste minimiert wird. Außerdem verschwindet die E-Mail-Liste unmittelbar zu Beginn der Umstellung mit dem grauen Fensterhintergrund. Wir sind also noch nicht fertig.

Fügen Sie der onViewCreated-Methode in HomeFragment.kt die folgenden beiden Zeilen hinzu, um den Rückgabeübergang zu korrigieren:

HomeFragment.kt

postponeEnterTransition()
view.doOnPreDraw { startPostponedEnterTransition() }

Versuchen Sie, die App noch einmal auszuführen. Wenn Sie nach dem Öffnen einer E-Mail auf „Zurück“ tippen, wird die E-Mail wieder in der Liste minimiert. Sehr gut! Wir sollten die Animation weiter verbessern.

Das Problem, dass die E-Mail-Liste verschwindet, besteht darin, dass das aktuelle Fragment sofort entfernt und durch das neue eingehende Fragment ersetzt wird, wenn Sie mithilfe der Navigationskomponente zu einem neuen Fragment navigieren. Wenn die E-Mail-Liste auch nach dem Ersetzen sichtbar bleiben soll, können Sie HomeFragment einen Ausgang hinzufügen.

Fügen Sie der Methode HomeFragment onEmailClicked das folgende Snippet hinzu, damit die Liste der E-Mails beim Verlassen und Wiederbetreten subtil skaliert wird:

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()
}

Um sicherzustellen, dass der Übergang MaterialElevationScale auf den Startbildschirm als Ganzes und nicht auf die einzelnen Ansichten in der Hierarchie angewendet wird, markieren Sie RecyclerView in fragment_home.xml als Übergangsgruppe.

fragment_home.xml

android:transitionGroup="true"

In dieser Phase sollten Sie eine voll funktionsfähige Containertransformation haben. Wenn Sie auf eine E-Mail klicken, wird das Listenelement in einem Detailbildschirm maximiert und die Liste der E-Mails minimiert. Wenn Sie auf „Zurück“ drücken, wird der Bildschirm mit den E-Mail-Details wieder zu einem Listenelement minimiert, während die Liste der E-Mails hochskaliert wird.

9df2b39d5a150418.gif

5. Container-Transformationsübergang vom FAB zur Seite zum Verfassen von E-Mails hinzufügen

Fahren wir mit der Containertransformation fort und fügen Sie einen Übergang von der unverankerten Aktionsschaltfläche zu ComposeFragment hinzu, um die UAS auf eine neue E-Mail zu erweitern, die vom Nutzer geschrieben werden soll. Führen Sie zuerst die App noch einmal aus und klicken Sie auf die UAS. Sie sehen dann, dass es beim Starten des Bildschirms zum Verfassen von E-Mails keine Umstellung gibt.

d242c9708abd382c.gif

Wir verwenden zwar dieselbe Übergangsklasse, aber die Konfiguration dieser Instanz wird anders sein, da sich die UAS in MainActivity befindet und die ComposeFragment im Navigationshostcontainer MainActivity platziert wird.

Fügen Sie in ComposeFragment.kt der Methode onViewCreated das folgende Snippet hinzu. Achten Sie dabei darauf, die androidx.transition-Version von Slide zu importieren.

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)
}

Neben den Parametern, die zur Konfiguration der vorherigen Containertransformation verwendet wurden, werden hier auch startView und endView manuell festgelegt. Anstatt transitionName-Attribute zu verwenden, um dem Android Transition-System mitzuteilen, welche Ansichten umgewandelt werden sollen, können Sie diese bei Bedarf manuell angeben.

Führen Sie die App jetzt noch einmal aus. Der Floating Action Button sollte sich in den Bildschirm zum Verfassen von Nachrichten verwandeln (siehe GIF am Ende dieses Schritts).

Ähnlich wie im vorherigen Schritt müssen Sie HomeFragment einen Übergang hinzufügen, damit er nicht verschwindet, nachdem er entfernt und durch ComposeFragment ersetzt wurde.

Kopieren Sie das Snippet unten in die Methode navigateToCompose in MainActivity, bevor Sie NavController navigate aufrufen.

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()
   }
}

Das war's für diesen Schritt. Der Übergang vom UAS-Bildschirm zum Erstellen sollte wie folgt aussehen:

81b68391ac4b0a9.gif

6. Gemeinsamen Z‑Achsen-Übergang vom Suchsymbol zur Suchansicht hinzufügen

In diesem Schritt fügen wir einen Übergang vom Suchsymbol zur Suchansicht im Vollbildmodus hinzu. Da bei dieser Navigationsänderung kein persistenter Container verwendet wird, können wir einen gemeinsamen Z‑Achsenübergang verwenden, um die räumliche Beziehung zwischen den beiden Bildschirmen zu verstärken und anzuzeigen, dass man sich in der Hierarchie der App um eine Ebene nach oben bewegt.

Bevor Sie zusätzlichen Code hinzufügen, starten Sie die App und tippen Sie rechts unten auf dem Bildschirm auf das Suchsymbol. Daraufhin sollte der Bildschirm für die Suchansicht ohne Übergang angezeigt werden.

499e1a677b4216bb.gif

Suchen Sie zuerst die Methode navigateToSearch in MainActivity und fügen Sie das folgende Code-Snippet vor dem NavController navigate-Methodenaufruf ein, um den Exit des aktuellen Fragments einzurichten und die Übergänge der Z-Achse von MaterialSharedAxis noch einmal einzugeben.

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()
   }
}

Fügen Sie als Nächstes der Methode onCreate in SearchFragment das folgende Code-Snippet hinzu. Damit werden die Ein- und Rückgänge vom Typ MaterialSharedAxis konfiguriert.

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()
}

Um sicherzustellen, dass der Übergang MaterialSharedAxis auf den Suchbildschirm als Ganzes und nicht auf die einzelnen Ansichten in der Hierarchie angewendet wird, markieren Sie LinearLayout in fragment_search.xml als Übergangsgruppe.

fragment_search.xml

android:transitionGroup="true"

Fertig! Starten Sie die App jetzt noch einmal und tippen Sie auf das Suchsymbol. Die Startbildschirme und Suchansichtsbildschirme sollten gleichzeitig entlang der Z-Achse in der Tiefe verblassen und skaliert werden, um einen nahtlosen Übergang zwischen den beiden Bildschirmen zu schaffen.

e5c0b0a130e807db.gif

7. Zwischen den Seiten des Postfachs den Übergang „Weich ausblenden“ hinzufügen

In diesem Schritt fügen wir einen Übergang zwischen verschiedenen Postfächern hinzu. Da wir keine räumliche oder hierarchische Beziehung betonen möchten, verwenden wir einen Fade-Through-Effekt, um einen einfachen "Wechsel" zwischen E-Mail-Listen durchzuführen.

Bevor Sie zusätzlichen Code hinzufügen, versuchen Sie, die App auszuführen, auf das Antwort-Logo in der unteren App-Leiste zu tippen und das Postfach zu wechseln. Die Liste der E-Mail-Adressen sollte sich ohne Übergang ändern.

2c874c0a4588e8fb.gif

Suchen Sie zuerst die Methode navigateToHome in MainActivity und fügen Sie das folgende Code-Snippet vor dem navigate-Methodenaufruf NavController ein, um den Exit-MaterialFadeThrough-Übergang des aktuellen Fragments einzurichten.

MainActivity.kt

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

Öffnen Sie als Nächstes HomeFragment. Legen Sie in onCreate den enterTransition des Fragments auf eine neue Instanz von MaterialFadeThrough fest.

HomeFragment.kt

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

Starten Sie die App neu. Wenn Sie die untere Navigationsleiste öffnen und den Posteingang wechseln, sollte die aktuelle E-Mail-Liste verblassen und verkleinert werden, während die neue Liste verblasst und vergrößert wird. Sehr gut!

f61dfd58ea7bd3fd.gif

8. Container-Transformation vom E-Mail-Adressen-Chip zur Kartenansicht hinzufügen

In diesem Schritt fügen Sie einen Übergang hinzu, der einen Chip in eine Pop-up-Karte umwandelt. Hier wird eine Containertransformation verwendet, um den Nutzer darüber zu informieren, dass sich die im Pop-up ausgeführte Aktion auf den Chip auswirkt, von dem das Pop-up stammt.

Bevor Sie Code hinzufügen, führen Sie die Antwort-App aus, klicken Sie auf eine E-Mail, auf die UAS für „Antworten“ und versuchen Sie dann, auf den Kontakt-Chip eines Empfängers zu klicken. Der Chip sollte sofort verschwinden und eine Karte mit den E-Mail-Adressen für diesen Kontakt ohne Animationen erscheinen.

6200c682da2382d5.gif

In diesem Schritt arbeiten Sie in ComposeFragment. Dem ComposeFragment-Layout wurden bereits Empfänger-Chips (standardmäßig sichtbar) und eine Empfängerkarte (standardmäßig ausgeblendet) hinzugefügt. Ein Empfänger-Chip und diese Karte sind die beiden Ansichten, zwischen denen Sie eine Containertransformation erstellen.

Öffnen Sie zuerst ComposeFragment und suchen Sie nach der Methode expandChip. Diese Methode wird aufgerufen, wenn auf die angegebene chip geklickt wird. Fügen Sie das folgende Code-Snippet oberhalb der Zeilen ein, die die Sichtbarkeit von recipientCardView und chip tauschen. Dadurch wird die über beginDelayedTransition registrierte Containertransformation ausgelöst.

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)

Wenn Sie die App jetzt ausführen, sollte sich der Chip in eine Karte mit E-Mail-Adressen für den Empfänger verwandeln. Als Nächstes konfigurieren wir den Rückgabeübergang, damit die Karte wieder in den Chip eingefahren wird.

Fügen Sie in der collapseChip-Methode in ComposeFragment das folgende Code-Snippet hinzu, um die Karte wieder in den Chip einzufahren.

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)

Starten Sie die App noch einmal. Wenn Sie auf den Chip klicken, wird er zu einer Karte maximiert. Wenn Sie auf die Karte klicken, wird sie wieder minimiert. Sehr gut!

e823b28e2890e05d.gif

9. Fertig

Mit weniger als 100 Zeilen Kotlin-Code und grundlegendem XML-Markup hat die MDC-Android-Bibliothek dir dabei geholfen, wunderschöne Übergänge in einer vorhandenen App zu erstellen, die den Material Design-Richtlinien entspricht und auf allen Android-Geräten einheitlich aussieht und funktioniert.

454a47ba96017a25.gif

Weiteres Vorgehen

Weitere Informationen zum Material-Bewegungssystem findest du in der Spezifikation und in der vollständigen Entwicklerdokumentation. Versuche auch, deiner App einige Material-Übergänge hinzuzufügen.

Vielen Dank, dass Sie Material Motion ausprobiert haben. Wir hoffen, dieses Codelab hat Ihnen gefallen.

Ich konnte dieses Codelab mit angemessenem Zeit- und Arbeitsaufwand abschließen

Stimme vollkommen zu Stimme zu Neutral Stimme nicht zu Stimme überhaupt nicht zu

Ich möchte das Material Motion-System auch in Zukunft verwenden.

Stimme vollkommen zu Stimme zu Neutral Stimme nicht zu Stimme überhaupt nicht zu