Tworzenie pięknych przejść dzięki Material Motion na Androida

1. Wprowadzenie

Material Design to system tworzenia atrakcyjnych i funkcjonalnych produktów cyfrowych. Łącząc styl, branding, interakcje i ruch w spójny zestaw zasad i komponentów, zespoły produktowe mogą w pełni wykorzystać swój potencjał projektowy.

logo_components_color_2x_web_96dp.png

Komponenty Material Design (MDC) pomagają deweloperom wdrażać Material Design. MDC zostało stworzone przez zespół inżynierów i projektantów UX w Google. Zawiera dziesiątki atrakcyjnych i funkcjonalnych komponentów interfejsu, które są dostępne na platformach Android, iOS, internetowej i Flutter.material.io/develop

Czym jest system ruchu Material na Androida?

System ruchu Material na Androida to zestaw wzorców przejść w bibliotece MDC-Android, które pomagają użytkownikom zrozumieć aplikację i się po niej poruszać, zgodnie z opisem w wytycznych Material Design.

Oto 4 główne wzorce przejść w Material:

  • Przekształcenie kontenera:przejścia między elementami interfejsu, które zawierają kontener; tworzy widoczne połączenie między dwoma różnymi elementami interfejsu, płynnie przekształcając jeden element w drugi.
  • Wspólna oś:przejścia między elementami interfejsu, między którymi istnieje związek przestrzenny lub nawigacyjny; używa wspólnej transformacji na osi x, y lub z do wzmocnienia związku między elementami.
  • Przenikanie:przejścia między elementami interfejsu, między którymi nie ma wyraźnego związku. Wykorzystuje sekwencyjne zanikanie i pojawianie się z skalowaniem elementu przychodzącego.
  • Zanikanie:przeznaczone dla elementów interfejsu, które pojawiają się lub znikają na ekranie.

Biblioteka MDC-Android oferuje klasy przejść dla tych wzorców, które są oparte na bibliotece przejść AndroidX (androidx.transition) i platformie przejść Androida (android.transition):

AndroidX

  • Dostępne w pakiecie com.google.android.material.transition
  • Obsługuje poziom API 14 lub nowszy
  • Obsługuje fragmenty i widoki, ale nie aktywności ani okna
  • Zawiera poprawki błędów przeniesione z nowszych wersji i zapewnia spójne działanie na różnych poziomach interfejsu API.

Framework

  • Dostępne w pakiecie com.google.android.material.transition.platform
  • Obsługuje poziom API 21 lub wyższy
  • Obsługuje fragmenty, widoki, aktywności i okna
  • Poprawki błędów nie są przenoszone do starszych wersji i mogą działać inaczej na różnych poziomach API.

W tym ćwiczeniu będziesz używać przejść Material opartych na bibliotece AndroidX, co oznacza, że skupisz się głównie na fragmentach i widokach.

Co utworzysz

Z tego ćwiczenia dowiesz się, jak w przykładowej aplikacji do poczty e-mail na Androida o nazwie Reply w języku Kotlin utworzyć przejścia, aby pokazać, jak za pomocą przejść z biblioteki MDC-Android dostosować wygląd i działanie aplikacji.

Otrzymasz kod startowy aplikacji Reply i dodasz do niej te przejścia Material, które możesz zobaczyć na GIF-ie poniżej:

  • Przejście Przekształcenie kontenera z listy e-maili na stronę szczegółów e-maila
  • Przejście przekształcenia kontenera z przycisku FAB na stronę tworzenia e-maila
  • Przejście wspólnej osi Z od ikony wyszukiwania do strony widoku wyszukiwania
  • przejście Zanikanie między stronami skrzynki pocztowej,
  • Przejście Container Transform z elementu dotyczącego adresu e-mail do widoku karty

Domena żądanego elementu iframe (youtu.be) nie została dodana do białej listy.

Czego potrzebujesz

  • Podstawowa wiedza na temat programowania na Androida i języka Kotlin
  • Android Studio (jeśli nie masz jeszcze tego środowiska, pobierz je tutaj).
  • emulator lub urządzenie z Androidem (dostępne w Androidzie Studio);
  • Przykładowy kod (patrz następny krok)

Jak oceniasz swoje doświadczenie w tworzeniu aplikacji na Androida?

Początkujący Średnio zaawansowany Zaawansowany

2. Konfigurowanie środowiska programistycznego

Uruchom Android Studio

Po otwarciu Androida Studio powinno się wyświetlić okno „Welcome to Android Studio” (Witamy w Androidzie Studio). Jeśli jednak uruchamiasz Android Studio po raz pierwszy, wykonaj czynności opisane w Kreatorze konfiguracji Androida Studio, używając wartości domyślnych. Pobranie i zainstalowanie niezbędnych plików może potrwać kilka minut, więc możesz pozostawić ten proces w tle i przejść do następnej sekcji.

Opcja 1. Sklonuj aplikację z ćwiczenia dla początkujących z GitHub

Aby skopiować ten codelab z GitHuba, uruchom te polecenia:

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

Opcja 2: pobierz plik ZIP z aplikacją codelab na początek.

Aplikacja startowa znajduje się w katalogu material-components-android-motion-codelab-develop.

Wczytaj kod startowy w Android Studio

  1. Gdy kreator konfiguracji zakończy działanie i wyświetli się okno Witamy w Android Studio, kliknij Otwórz istniejący projekt Android Studio.

e3f200327a67a53.png

  1. Przejdź do katalogu, w którym został zainstalowany przykładowy kod, i wybierz katalog z przykładem, aby otworzyć projekt.
  2. Poczekaj chwilę, aż Android Studio utworzy i zsynchronizuje projekt. Wskaźniki aktywności w dolnej części okna Android Studio będą pokazywać postęp.
  1. W tym momencie Android Studio może zgłosić błędy kompilacji, ponieważ brakuje Ci pakietu SDK Androida lub narzędzi do kompilacji, np. takich jak te pokazane poniżej. Postępuj zgodnie z instrukcjami w Android Studio, aby zainstalować lub zaktualizować te komponenty i zsynchronizować projekt. Jeśli nadal masz problemy, postępuj zgodnie z instrukcjami aktualizacji narzędzi za pomocą Menedżera SDK.

6e026ae171f5b1eb.png

Sprawdzanie zależności projektu

Projekt musi być zależny od biblioteki MDC-Android. Pobrany kod przykładowy powinien już zawierać tę zależność, ale sprawdźmy konfigurację, aby się upewnić.

Otwórz plik build.gradle modułu app i upewnij się, że blok dependencies zawiera zależność od MDC-Android:

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

Uruchom aplikację startową

  1. Upewnij się, że konfiguracja kompilacji po lewej stronie wyboru urządzenia to app.
  2. Naciśnij zielony przycisk Uruchom / Odtwórz, aby skompilować i uruchomić aplikację.

24218d0a6ae25803.png

  1. Jeśli w oknie Select Deployment Target (Wybierz miejsce docelowe wdrożenia) na liście dostępnych urządzeń widzisz już urządzenie z Androidem, przejdź do kroku 8. W przeciwnym razie kliknij Utwórz nowe urządzenie wirtualne.
  2. Na ekranie Wybierz sprzęt wybierz telefon, np. Pixel 3, a potem kliknij Dalej.
  3. Na ekranie Obraz systemu wybierz ostatnią wersję Androida, najlepiej z najwyższym poziomem interfejsu API. Jeśli nie jest zainstalowana, kliknij wyświetlony link Pobierz i pobierz aplikację.
  4. Kliknij Dalej.
  5. Na ekranie Android Virtual Device (AVD) (urządzenie wirtualne z Androidem) pozostaw ustawienia bez zmian i kliknij Finish (Zakończ).
  6. W oknie docelowym wdrożenia wybierz urządzenie z Androidem.
  7. Kliknij OK.
  8. Android Studio skompiluje aplikację, wdroży ją i automatycznie otworzy na urządzeniu docelowym.

Gotowe! Kod startowy strony głównej aplikacji Reply powinien być uruchomiony w emulatorze. Powinna się wyświetlić skrzynka odbiorcza z listą e-maili.

cc73eb0d0f779035.png

Opcjonalnie: spowolnienie animacji na urządzeniu

Ten przewodnik obejmuje szybkie, ale dopracowane przejścia, dlatego podczas implementacji warto spowolnić animacje na urządzeniu, aby obserwować niektóre szczegóły przejść. Możesz to zrobić za pomocą adbpoleceń powłoki lub kafelka Szybkich ustawień. Pamiętaj, że te metody spowalniania animacji na urządzeniu wpłyną na animacje poza aplikacją Odpowiedz.

Metoda 1. Polecenia powłoki ADB

Aby spowolnić animacje na urządzeniu 10-krotnie, możesz uruchomić te polecenia z poziomu wiersza poleceń:

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

Aby przywrócić normalną szybkość animacji na urządzeniu, uruchom te polecenia:

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

Metoda 2. Kafelek Szybkich ustawień

Aby skonfigurować kafelek Szybkich ustawień, najpierw włącz na urządzeniu ustawienia programisty (jeśli nie zostały jeszcze włączone):

  1. Otwórz aplikację „Ustawienia” na urządzeniu.
  2. Przewiń w dół i kliknij „Informacje o emulowanym urządzeniu”.
  3. Przewiń na dół i szybko klikaj „Numer kompilacji”, aż włączysz ustawienia programisty.

Następnie w aplikacji „Ustawienia” na urządzeniu wykonaj te czynności, aby włączyć kafelek Szybkich ustawień:

  1. Kliknij ikonę wyszukiwania lub pasek wyszukiwania u góry ekranu.
  2. Wpisz „kafelki” w polu wyszukiwania.
  3. Kliknij wiersz „Kafelki szybkich ustawień dla programisty”.
  4. Kliknij przełącznik „Skala animacji okna”.

Na koniec w trakcie wykonywania ćwiczeń w Codelabs przesuwaj palcem z góry ekranu w dół, aby otworzyć obszar powiadomień systemowych, i używaj ikony c7e3f98200023f6a.png, aby przełączać się między animacjami o normalnej i wolnej szybkości.

3. Zapoznaj się z kodem przykładowej aplikacji

Przyjrzyjmy się kodowi. Udostępniliśmy aplikację, która używa biblioteki komponentu nawigacji Jetpack do poruszania się między kilkoma różnymi fragmentami w ramach jednej aktywności, MainActivity:

  • HomeFragment: wyświetla listę e-maili.
  • EmailFragment:wyświetla pojedynczy, pełny e-mail.
  • ComposeFragment: umożliwia tworzenie nowego e-maila.
  • SearchFragment: wyświetla widok wyszukiwania.

Najpierw, aby dowiedzieć się, jak skonfigurowany jest wykres nawigacji aplikacji, otwórz plik navigation_graph.xml w katalogu 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>

Zwróć uwagę, że wszystkie wymienione wyżej fragmenty są obecne, a domyślny fragment uruchamiania jest ustawiony na HomeFragment za pomocą app:startDestination="@id/homeFragment". Ta definicja XML wykresu miejsca docelowego fragmentu, a także działań, zawiera informacje dla wygenerowanego kodu nawigacji w Kotlinie, który napotkasz podczas podłączania przejść.

activity_main.xml

Następnie przyjrzyj się activity_main.xmlukładowiapp -> src -> main -> res -> layout w katalogu. Zobaczysz element NavHostFragment skonfigurowany za pomocą powyższego wykresu nawigacji:

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

Ten element NavHostFragment wypełnia ekran i obsługuje wszystkie zmiany nawigacji fragmentów pełnoekranowych w aplikacji. Element BottomAppBar i jego zakotwiczony element FloatingActionButton, również w activity_main.xml, są umieszczone nad bieżącym fragmentem wyświetlanym przez element NavHostFragment, dlatego będą widoczne lub ukryte w zależności od miejsca docelowego fragmentu zgodnie z podanym kodem przykładowej aplikacji.

Dodatkowo BottomNavDrawerFragment w activity_main.xml to dolna szuflada zawierająca menu do poruszania się między różnymi skrzynkami pocztowymi, które jest warunkowo wyświetlane za pomocą przycisku z logo BottomAppBar Odpowiedz.

MainActivity.kt

Na koniec, aby zobaczyć przykład użycia działania nawigacji, otwórz plik MainActivity.kt w katalogu app -> src -> main -> java -> com.materialstudies.reply.ui. Znajdź funkcję navigateToSearch(), która powinna wyglądać tak:

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

Pokazuje to, jak przejść do strony widoku wyszukiwania bez niestandardowego przejścia. W tym ćwiczeniu przyjrzysz się plikowi MainActivity i 4 głównym fragmentom aplikacji Reply, aby skonfigurować przejścia Material, które będą działać w połączeniu z różnymi działaniami nawigacyjnymi w aplikacji.

Znasz już kod startowy, więc teraz zaimplementujmy pierwsze przejście.

4. Dodawanie przejścia Przekształcenie kontenera z listy e-maili na stronę szczegółów e-maila

Na początek dodaj przejście po kliknięciu e-maila. W przypadku tej zmiany nawigacji wzorzec przekształcenia kontenera jest odpowiedni, ponieważ jest przeznaczony dla przejść między elementami interfejsu, które zawierają kontener. Tworzy on widoczne połączenie między dwoma elementami interfejsu.

Zanim dodasz jakikolwiek kod, spróbuj uruchomić aplikację Reply i kliknąć e-maila. Powinno to być proste cięcie, czyli ekran jest zastępowany bez przejścia:

f0e8a92eb2216bce.gif

Zacznij od dodania atrybutu transitionName do elementu MaterialCardViewemail_item_layout.xml, jak pokazano w tym fragmencie kodu:

email_item_layout.xml

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

Nazwa przejścia przyjmuje zasób tekstowy z parametrem. Musisz użyć identyfikatora każdego adresu e-mail, aby zapewnić, że każdy element transitionName w naszym EmailFragment jest unikalny.

Teraz, gdy masz już ustawioną nazwę przejścia elementu listy e-mail, zrób to samo w układzie szczegółów e-maila. W fragment_email.xml ustaw transitionName elementu MaterialCardView na ten zasób tekstowy:

fragment_email.xml

android:transitionName="@string/email_card_detail_transition_name"

W HomeFragment.kt zastąp kod w onEmailClicked poniższym fragmentem, aby utworzyć mapowanie widoku początkowego (element listy e-maili) i widoku końcowego (ekran szczegółów e-maila):

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)

Po skonfigurowaniu infrastruktury możesz utworzyć przekształcenie kontenera. W metodzie EmailFragment onCreate ustaw sharedElementEnterTransition na nową instancję MaterialContainerTransform (zaimportuj wersję com.google.android.material.transition zamiast wersji com.google.android.material.transition.platform), dodając ten fragment kodu:

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

Spróbuj ponownie uruchomić aplikację.

ed62cedec31da268.gif

Wszystko zaczyna wyglądać świetnie. Gdy klikniesz e-maila na liście e-maili, przekształcenie kontenera powinno rozwinąć element listy do strony z informacjami na pełnym ekranie. Zwróć jednak uwagę, że naciśnięcie przycisku Wstecz nie powoduje zwinięcia e-maila z powrotem na listę. Dodatkowo lista e-maili znika natychmiast na początku przejścia, a w jej miejscu pojawia się szare tło okna. To jeszcze nie koniec.

Aby naprawić przejście powrotne, dodaj te 2 wiersze do metody onViewCreatedHomeFragment.kt:

HomeFragment.kt

postponeEnterTransition()
view.doOnPreDraw { startPostponedEnterTransition() }

Spróbuj ponownie uruchomić aplikację. Jeśli po otwarciu e-maila naciśniesz przycisk Wstecz, e-mail zostanie z powrotem zwinięty na liście. Super! Ulepszajmy dalej animację.

Problem ze znikaniem listy e-maili wynika z tego, że podczas przechodzenia do nowego fragmentu za pomocą komponentu Navigation bieżący fragment jest natychmiast usuwany i zastępowany nowym fragmentem. Aby lista e-mailowa była widoczna nawet po zastąpieniu, możesz dodać przejście wyjścia do elementu HomeFragment.

Dodaj poniższy fragment kodu do metody HomeFragment onEmailClicked, aby lista e-maili subtelnie się skalowała w poziomie po wyjściu z niej i zmniejszała po ponownym wejściu:

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

Następnie, aby upewnić się, że przejście MaterialElevationScale jest stosowane do całego ekranu głównego, a nie do poszczególnych widoków w hierarchii, oznacz RecyclerViewfragment_home.xml jako grupę przejścia.

fragment_home.xml

android:transitionGroup="true"

Na tym etapie powinna być już w pełni działająca transformacja kontenera. Kliknięcie e-maila powoduje rozwinięcie elementu listy do ekranu szczegółów i cofnięcie listy e-maili. Naciśnięcie przycisku Wstecz powoduje zwinięcie ekranu szczegółów e-maila z powrotem do elementu listy i powiększenie go na liście e-maili.

9df2b39d5a150418.gif

5. Dodawanie przejścia przekształcenia kontenera z przycisku typu FAB na stronę tworzenia e-maila

Kontynuujmy przekształcanie kontenera i dodajmy przejście od pływającego przycisku polecenia do ComposeFragment, rozwijając przycisk typu FAB do postaci nowego e-maila, który użytkownik może napisać. Najpierw uruchom ponownie aplikację i kliknij przycisk typu FAB, aby sprawdzić, czy podczas uruchamiania ekranu tworzenia e-maila nie ma przejścia.

d242c9708abd382c.gif

Chociaż używamy tej samej klasy przejścia, sposób konfiguracji tej instancji będzie inny, ponieważ nasz przycisk typu FAB znajduje się w MainActivity, a ComposeFragment jest umieszczony w kontenerze hosta Navigation MainActivity.

ComposeFragment.kt dodaj ten fragment kodu do metody onViewCreated, pamiętając o zaimportowaniu wersji androidx.transition 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)
}

Oprócz parametrów używanych do konfigurowania poprzedniej transformacji kontenera, startViewendView są tutaj ustawiane ręcznie. Zamiast używać atrybutów transitionName, aby poinformować system przejść Androida, które widoki mają zostać przekształcone, możesz w razie potrzeby określić je ręcznie.

Teraz ponownie uruchom aplikację. Powinien pojawić się pływający przycisk czynności przekształcający się w ekran tworzenia (patrz GIF na końcu tego kroku).

Podobnie jak w poprzednim kroku musisz dodać przejście do HomeFragment, aby nie zniknęło po usunięciu i zastąpieniu przez ComposeFragment.

Skopiuj poniższy fragment kodu do metody navigateToCompose w pliku MainActivity przed wywołaniem 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()
   }
}

To wszystko w tym kroku. Przejście z przycisku typu FAB do ekranu tworzenia powinno wyglądać tak:

81b68391ac4b0a9.gif

6. Dodawanie przejścia Wspólna oś Z z ikony wyszukiwania na stronę widoku wyszukiwania

W tym kroku dodamy przejście od ikony wyszukiwania do widoku wyszukiwania na pełnym ekranie. Ponieważ w tej zmianie nawigacji nie ma trwałego kontenera, możemy użyć przejścia na wspólnej osi Z, aby wzmocnić relację przestrzenną między dwoma ekranami i wskazać przejście o jeden poziom wyżej w hierarchii aplikacji.

Zanim dodasz kolejny kod, spróbuj uruchomić aplikację i kliknąć ikonę wyszukiwania w prawym dolnym rogu ekranu. Powinien pojawić się ekran widoku wyszukiwania bez przejścia.

499e1a677b4216bb.gif

Na początek znajdź metodę navigateToSearchMainActivity i dodaj ten fragment kodu przed wywołaniem metody NavController navigate, aby skonfigurować przejścia osi Z MaterialSharedAxis dla bieżącego fragmentu.

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

Następnie dodaj ten fragment kodu do metody onCreate w pliku SearchFragment, która konfiguruje przejścia MaterialSharedAxis podczas wchodzenia i wychodzenia.

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

Aby przejście MaterialSharedAxis zostało zastosowane do całego ekranu wyszukiwania, a nie do poszczególnych widoków w hierarchii, oznacz LinearLayoutfragment_search.xml jako grupę przejścia.

fragment_search.xml

android:transitionGroup="true"

To wszystko. Teraz spróbuj ponownie uruchomić aplikację i kliknąć ikonę wyszukiwania. Ekrany widoku głównego i wyszukiwania powinny jednocześnie zanikać i skalować się wzdłuż osi Z, tworząc płynne przejście między nimi.

e5c0b0a130e807db.gif

7. Dodawanie przejścia z efektem zanikania między stronami skrzynki pocztowej

W tym kroku dodamy przejście między różnymi skrzynkami pocztowymi. Nie chcemy podkreślać przestrzennej ani hierarchicznej relacji, dlatego użyjemy przejścia z jednej listy e-maili do drugiej.

Zanim dodasz dodatkowy kod, spróbuj uruchomić aplikację, kliknąć logo Odpowiedz na dolnym pasku aplikacji i przełączyć skrzynki pocztowe. Lista e-maili powinna się zmieniać bez przejścia.

2c874c0a4588e8fb.gif

Na początek znajdź metodę navigateToHomeMainActivity i przed wywołaniem metody NavController navigate dodaj ten fragment kodu, aby skonfigurować przejście MaterialFadeThrough bieżącego fragmentu.

MainActivity.kt

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

Następnie otwórz HomeFragment. W onCreate ustaw enterTransition fragmentu na nowe wystąpienie MaterialFadeThrough.

HomeFragment.kt

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

Uruchom ponownie aplikację. Gdy otworzysz dolny panel nawigacji i zmienisz skrzynki pocztowe, bieżąca lista e-maili powinna zaniknąć i zmniejszyć się, a nowa lista powinna się pojawić i zwiększyć. Super!

f61dfd58ea7bd3fd.gif

8. Dodawanie przejścia Container Transform z elementu z adresem e-mail do widoku karty

W tym kroku dodasz przejście, które przekształci chip w wyskakującą kartę. W tym przypadku używana jest transformacja kontenera, aby poinformować użytkownika, że działanie podjęte w wyskakującym okienku wpłynie na element, z którego to okienko pochodzi.

Zanim dodasz jakikolwiek kod, uruchom aplikację Odpowiedz, kliknij e-maila, kliknij pływający przycisk czynności „Odpowiedz”, a następnie spróbuj kliknąć kartę kontaktu odbiorcy. Element powinien zniknąć natychmiast, a karta z adresami e-mail tego kontaktu powinna pojawić się bez animacji.

6200c682da2382d5.gif

Na tym etapie będziesz pracować w ComposeFragment. W układzie ComposeFragment są już dodane elementy odbiorcy (widoczne domyślnie) i karta odbiorcy (niewidoczna domyślnie). Chip odbiorcy i ta karta to 2 widoki, między którymi utworzysz przekształcenie kontenera.

Aby rozpocząć, otwórz ComposeFragment i znajdź metodę expandChip. Ta metoda jest wywoływana po kliknięciu podanego elementu chip. Dodaj ten fragment kodu nad wierszami, które zamieniają widoczność recipientCardViewchip. Spowoduje to wywołanie transformacji kontenera zarejestrowanej za pomocą 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)

Jeśli teraz uruchomisz aplikację, chip powinien przekształcić się w kartę z adresami e-mail odbiorcy. Następnie skonfigurujmy przejście powrotne, aby zwinąć kartę z powrotem do postaci elementu.

W metodzie collapseChipComposeFragment dodaj ten fragment kodu, aby zwinąć kartę z powrotem do elementu.

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)

Uruchom ponownie aplikację. Kliknięcie elementu powinno spowodować rozwinięcie go do postaci karty, a kliknięcie karty powinno spowodować jej zwinięcie z powrotem do postaci elementu. Super!

e823b28e2890e05d.gif

9. Wszystko gotowe

Biblioteka MDC-Android, która zawiera mniej niż 100 wierszy kodu Kotlin i podstawowe znaczniki XML, pomogła Ci utworzyć atrakcyjne przejścia w istniejącej aplikacji zgodnej z wytycznymi Material Design, a także zapewnić spójny wygląd i działanie na wszystkich urządzeniach z Androidem.

454a47ba96017a25.gif

Dalsze kroki

Więcej informacji o systemie ruchu Material znajdziesz w specyfikacji i pełnej dokumentacji dla deweloperów. Możesz też dodać do aplikacji przejścia Material.

Dziękujemy za wypróbowanie animacji Material. Mamy nadzieję, że to ćwiczenie było dla Ciebie przydatne.

Udało mi się ukończyć to ćwiczenie w rozsądnym czasie i przy rozsądnym nakładzie pracy.

Zdecydowanie się zgadzam Zgadzam się Nie mam zdania Nie zgadzam się Zdecydowanie się nie zgadzam

Chcę w przyszłości nadal korzystać z systemu ruchu Material

Zdecydowanie się zgadzam Zgadzam się Nie mam zdania Nie zgadzam się Zdecydowanie się nie zgadzam