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

1. Wprowadzenie

Material Design to system do tworzenia odważnych i pięknych produktów cyfrowych. Łącząc styl, budowanie marki, interakcję i ruch w ramach spójnego zestawu zasad i komponentów, zespoły zajmujące się poszczególnymi produktami i usługami 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 to biblioteka stworzona przez zespół inżynierów i projektantów UX w Google. Zawiera dziesiątki pięknych i funkcjonalnych komponentów UI. Jest dostępna na Androida, iOS, web i Flutter.material.io/develop

Czym jest system animacji Material Design na Androida?

System animacji Material Design na Androida to zestaw wzorów przejść w bibliotece MDC-Android, które mogą ułatwiać użytkownikom korzystanie z aplikacji i poruszanie się po niej. Więcej informacji znajdziesz w wytycznych dotyczących Material Design.

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

  • Przekształcenie kontenera: przejścia między elementami interfejsu zawierającymi 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, które są powiązane przestrzennie lub nawigacyjne. Wykorzystuje wspólne przekształcenie na osi x, y lub z w celu wzmocnienia relacji między elementami.
  • Przejście przez: przejścia między elementami interfejsu, między którymi nie ma wyraźnego związku; wykorzystuje sekwencyjne zanikanie i włączanie z jednoczesnym skalowaniem elementu.
  • Zanikanie: przeznaczone do elementów interfejsu, które pojawiają się lub znikają na ekranie.

Biblioteka MDC-Android udostępnia klasy przejść dla tych wzorów. Zostały one utworzone na podstawie biblioteki AndroidX Transition (androidx.transition) i ramy Android Transition Framework (android.transition):

AndroidX

  • Dostępne w opakowaniu com.google.android.material.transition
  • Obsługuje interfejs API poziomu 14 lub nowszego
  • Obsługuje fragmenty i widoki, ale nie aktywności ani okna.
  • Zawiera wsteczne poprawki błędów i spójne działanie na różnych poziomach interfejsu API.

Struktura

  • Dostępne w opakowaniu com.google.android.material.transition.platform
  • Obsługuje interfejs API poziomu 21 lub nowszego
  • Obsługuje fragmenty, widoki, aktywności i okna
  • poprawki błędów nie są przenoszone wstecz i mogą działać inaczej na różnych poziomach interfejsu API;

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

Co utworzysz

Dzięki temu ćwiczeniu w Codelabs dowiesz się, jak tworzyć przejścia z przykładowej aplikacji e-mail na Androida o nazwie Reply, przy użyciu Kotlin, aby zademonstrować, jak korzystać z przejścia z biblioteki MDC-Android do dostosowania wyglądu i sposobu działania aplikacji.

Dostaniesz kod startowy aplikacji Reply. Będziesz musiał(-aś) wdrożyć w niej te przejścia w stylu Material Design, które możesz zobaczyć na GIF-ie z ukończonego ćwiczenia:

  • Transformer kontenera – przejście ze strony z listą e-mailową na stronę z informacjami o e-mailu
  • Przejście z przycisku szybkiego dostępu do strony tworzenia e-maila w Container Transform
  • Wspólna oś z: przejście od ikony wyszukiwania do strony widoku wyszukiwania
  • Przechodzenie między stronami skrzynki pocztowej Fade Through
  • Przejście z przekształcenia kontenera z elementu adresu e-mail na widok karty

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

Czego potrzebujesz

  • podstawowa wiedza o programowaniu aplikacji na Androida i Kotlinie;
  • Android Studio (pobierz tę aplikację stąd, jeśli jeszcze jej nie masz)
  • emulator lub urządzenie z Androidem (dostępne w Android Studio).
  • Przykładowy kod (patrz następny krok)

Jak oceniasz swój poziom doświadczenia w tworzeniu aplikacji na Androida?

Początkujący Średnio zaawansowany Zaawansowany

2. Konfigurowanie środowiska programistycznego

Uruchom Android Studio

Gdy otworzysz Android Studio, powinno wyświetlić się okno „Welcome to Android Studio”. Jeśli jednak uruchamiasz Android Studio po raz pierwszy, wykonaj instrukcje Kreatora konfiguracji Android Studio, stosując wartości domyślne. Pobranie i zainstalowanie niezbędnych plików może potrwać kilka minut, więc w każdej sekcji możesz pozostawić je uruchomione w tle.

Opcja 1. Skopiuj starterową aplikację z GitHuba do Codelab

Aby skopiować ten laboratorium 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 aplikacji startowej z programowania

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

Wczytywanie kodu startowego w Android Studio

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

e3f200327a67a53.png

  1. Przejdź do katalogu, w którym zainstalowano przykładowy kod, i wybierz katalog z przykładami, aby otworzyć projekt.
  2. Poczekaj chwilę, aż Android Studio utworzy i zsynchronizuje projekt. Postęp prac będzie widoczny na wskaźnikach aktywności u dołu okna Android Studio.
  1. W tym momencie Android Studio może wyświetlić błędy kompilacji, ponieważ brakuje pakietu Android SDK lub narzędzi do kompilacji, takich jak pokazane poniżej. Postępuj zgodnie z instrukcjami w Android Studio, aby zainstalować lub zaktualizować te aplikacje i zsynchronizować projekt. Jeśli nadal masz problemy, postępuj zgodnie z instrukcjami podanymi w przewodniku dotyczącym aktualizowania narzędzi za pomocą Menedżera SDK.

6e026ae171f5b1eb.png

Sprawdzanie zależności projektu

Projekt musi być zależny od biblioteki MDC-Android. Pobrane przez Ciebie przykładowe kody powinny już zawierać tę zależność, ale sprawdźmy konfigurację, aby się upewnić.

Przejdź do pliku 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'

Uruchomienie aplikacji startowej

  1. Upewnij się, że konfiguracja kompilacji po lewej stronie wybranego urządzenia to app.
  2. Aby skompilować i uruchomić aplikację, naciśnij zielony przycisk Uruchom / Graj.

24218d0a6ae25803.png

  1. Jeśli masz już urządzenie z Androidem na liście dostępnych urządzeń, w oknie Wybierz cel wdrożenia przejdź do kroku 8. W przeciwnym razie kliknij Create New Virtual Device (Utwórz nowe urządzenie wirtualne).
  2. Na ekranie Wybierz sprzęt wybierz telefon, na przykład Pixel 3, i kliknij Dalej.
  3. Na ekranie Obraz systemu wybierz najnowszą wersję Androida, najlepiej najwyższy poziom interfejsu API. Jeśli aplikacja nie jest zainstalowana, kliknij widoczny link Pobierz i dokończ pobieranie.
  4. Kliknij Dalej.
  5. Na ekranie Urządzenie wirtualne z Androidem (AVD) pozostaw ustawienia bez zmian i kliknij Zakończ.
  6. W oknie docelowym wdrożenia wybierz urządzenie z Androidem.
  7. Kliknij OK.
  8. Android Studio kompiluje aplikację, wdraża ją i automatycznie otwiera na urządzeniu docelowym.

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

cc73eb0d0f779035.png

Opcjonalnie: zwolnienie animacji na urządzeniu

Ponieważ to ćwiczenie obejmuje szybkie, ale dopracowane przejścia, warto spowolnić animacje na urządzeniu, aby podczas implementacji można było zauważyć więcej szczegółów. Można to zrobić za pomocą poleceń powłoki adb lub kafelka Szybkich ustawień. Pamiętaj, że te metody zwolnienia animacji na urządzeniu wpłyną również na animacje na urządzeniu poza aplikacją Reply.

Metoda 1. Za pomocą poleceń powłoki ADB

Aby spowolnić animacje na urządzeniu 10 razy, możesz uruchomić te polecenia w wierszu 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ć normalne działanie 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ń, możesz też najpierw włączyć na urządzeniu ustawienia programisty:

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

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

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

Na koniec podczas ćwiczenia w programowaniu wysuń obszar powiadomień systemowych z góry ekranu i za pomocą ikony c7e3f98200023f6a.png przełącz się między animacjami o niskiej i normalnej szybkości.

3. Zapoznaj się z kodem przykładowej aplikacji

Spójrzmy na kod. Udostępniamy aplikację, która korzysta z biblioteki komponentu Nawigacja Jetpacka do przechodzenia między kilkoma różnymi fragmentami w ramach jednej aktywności, MainActivity:

  • HomeFragment: wyświetla listę adresów e-mail.
  • EmailFragment: wyświetla jeden pełny e-mail.
  • ComposeFragment: umożliwia tworzenie nowych e-maili.
  • SearchFragment: wyświetla widok wyszukiwania.

Aby dowiedzieć się, jak skonfigurowano wykres nawigacji w 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ę na to, że obecne są wszystkie wymienione powyżej fragmenty, a domyślny fragment uruchamiania jest ustawiony na HomeFragment w app:startDestination="@id/homeFragment". Ta definicja XML wykresu docelowego fragmentu, jak również działania, zawiera informacje dla wygenerowanego kodu nawigacyjnego Kotlin, który napotkasz podczas podłączania przejść.

activity_main.xml

Następnie sprawdź układ activity_main.xml w katalogu app -> src -> main -> res -> layout. Zobaczysz NavHostFragment skonfigurowany za pomocą grafu nawigacyjnego z powyższego okna:

<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 NavHostFragment wypełnia ekran i obsługuje wszystkie zmiany dotyczące nawigacji w fragmentach pełnoekranowych w aplikacji. Element BottomAppBar i jego zakotwiczony element FloatingActionButton, również w activity_main.xml, są rozmieszczone na wierzchu bieżącego fragmentu wyświetlanego przez NavHostFragment, a dlatego będą wyświetlane lub ukryte w zależności od miejsca docelowego fragmentu w zamieszczonym przykładowym kodzie aplikacji.

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

MainActivity.kt

Aby zobaczyć przykładowe działanie nawigacji, otwórz plik MainActivity.kt w katalogu app -> src -> main -> java -> com.materialstudies.reply.ui. Odszukaj funkcję navigateToSearch(), która powinna wyglądać tak:

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

Tutaj możesz zobaczyć, jak możesz przejść do strony widoku wyszukiwania bez niestandardowych przejść. W tym ćwiczeniu zapoznasz się z klasą MainActivity i 4 głównymi fragmentami aplikacji Reply, aby skonfigurować przejścia w stylu Material Design, które współpracują z różnymi działaniami nawigacyjnymi w aplikacji.

Teraz, gdy znasz już kod startowy, zaimplementujmy pierwszą zmianę.

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

Na początek dodaj przejście, klikając e-maila. W przypadku tej zmiany w nawigacji dobrze sprawdzi się wzorzec przekształcenia kontenera, ponieważ jest on przeznaczony do przejść między elementami interfejsu, które zawierają kontener. Ten wzorzec tworzy widoczne połączenie między 2 elementami interfejsu.

Zanim dodasz kod, uruchom aplikację Reply i kliknij e-maila. Powinien wykonać proste cięcie skokowe, co oznacza, że ekran będzie zastępowany brakiem przejścia:

f0e8a92eb2216bce.gif

Zacznij od dodania atrybutu transitionName do elementu MaterialCardView w pliku email_item_layout.xml, jak w tym fragmencie:

email_item_layout.xml

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

Nazwa przejścia przyjmuje zasób ciągu znaków z parametrem. Musisz użyć identyfikatora każdego adresu e-mail, aby mieć pewność, że każdy transitionName w naszym EmailFragment jest unikalny.

Masz już ustawioną nazwę przejścia elementu listy e-mailowej, więc zróbmy to samo w układzie szczegółów e-maila. W pliku fragment_email.xml ustaw wartość transitionName dla zasobu MaterialCardView na ten ciąg znaków:

fragment_email.xml

android:transitionName="@string/email_card_detail_transition_name"

W pliku HomeFragment.kt zastąp kod w pliku onEmailClicked tym fragmentem kodu, 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 instalacji hydraulicznej możesz utworzyć przekształcenie kontenera. W metodzie EmailFragment onCreate ustaw sharedElementEnterTransition na nowe wystąpienie MaterialContainerTransform (importując wersję com.google.android.material.transition zamiast 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))
}

Teraz spróbuj ponownie uruchomić aplikację.

ed62cedec31da268.gif

Wszystko zaczyna się wyświetlać. Gdy klikniesz e-maila na liście e-maili, transformacja kontenera powinna rozwinąć element listy na pełną stronę szczegółów. Pamiętaj jednak, że naciśnięcie Wstecz nie powoduje zwijania e-maila z powrotem na listę. Dodatkowo lista e-mailowa znika natychmiast na początku przejścia i ma szare tło okna. To jeszcze nie koniec.

Aby naprawić przejście zwrotne, dodaj do metody onViewCreated w pliku HomeFragment.kt te 2 wiersze kodu:

HomeFragment.kt

postponeEnterTransition()
view.doOnPreDraw { startPostponedEnterTransition() }

Spróbuj ponownie uruchomić aplikację. Naciśnięcie przycisku Wstecz po otwarciu e-maila spowoduje jego zwinięcie z powrotem na listę. Super! Poprawiajmy animację.

Problem znikania listy e-maili występuje, ponieważ podczas przechodzenia do nowego fragmentu za pomocą komponentu nawigacji bieżący fragment jest natychmiast usuwany i zastępowany nowym, nadchodzącym fragmentem. Aby lista e-maili była widoczna nawet po jej zastąpieniu, możesz dodać przejście wyjścia do HomeFragment.

Dodaj poniższy fragment kodu do metody HomeFragment onEmailClicked, aby lista adresów e-mail była subtelnie skalowana w poziomie przy wychodzeniu i z powrotem przy otwieraniu:

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

Aby przejście MaterialElevationScale zostało zastosowane do całego ekranu głównego, a nie do poszczególnych widoków w hierarchii, oznacz RecyclerView w elemencie fragment_home.xml jako grupę przejścia.

fragment_home.xml

android:transitionGroup="true"

Na tym etapie powinnaś/powinieneś mieć w pełni działającą transformację kontenera. Kliknięcie e-maila powoduje rozwinięcie elementu listy na ekranie z informacjami, a także cofnięcie listy e-maili. Naciśnięcie przycisku wstecz zwija ekran ze szczegółami e-maila z powrotem do elementu listy i skaluje go w górę na liście e-maili.

9df2b39d5a150418.gif

5. Dodawanie przejścia z przycisku szybkiego dostępu do strony tworzenia e-maila

Wróćmy do przekształcenia kontenera i dodamy przejście z pływającego przycisku polecenia do elementu ComposeFragment, rozwijając przycisk PPP do nowego e-maila do napisania przez użytkownika. Najpierw uruchom aplikację ponownie i kliknij przycisk FAB, aby zobaczyć, że po uruchomieniu ekranu tworzenia e-maila nie ma żadnego przejścia.

d242c9708abd382c.gif

Chociaż używamy tej samej klasy przejścia, sposób konfigurowania tego wystąpienia będzie inny, ponieważ przycisk FAB znajduje się w MainActivity, a element ComposeFragment jest umieszczony w kontenerze hosta nawigacji MainActivity.

W narzędziu ComposeFragment.kt dodaj poniższy fragment kodu do metody onViewCreated, pamiętając, aby zaimportować wersję androidx.transition metody 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 poprzedniego przekształcenia kontenera parametry startView i endView ustawiane są tu ręcznie. Zamiast używać atrybutów transitionName, aby poinformować system Android Transition o tym, które widoki należy przekształcić, możesz w razie potrzeby podać je ręcznie.

Uruchom ponownie aplikację. Skrót powinien przekształcić się w ekran tworzenia wiadomości (patrz GIF na końcu tego kroku).

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

Skopiuj podany niżej 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 na razie. Powinno nastąpić przejście z przycisku PPP do ekranu tworzenia wiadomości, który będzie podobny do tego:

81b68391ac4b0a9.gif

6. Dodaj przejście na wspólnej osi z od ikony wyszukiwania do strony widoku wyszukiwania

W tym kroku dodamy przejście z ikony wyszukiwania do widoku wyszukiwania na pełnym ekranie. Ponieważ w tej zmianie nawigacji nie występuje trwały kontener, możemy użyć przejścia na wspólnej osi Z, aby wzmocnić przestrzenny związek między 2 ekranami i wskazywać przejście o jeden poziom w hierarchii aplikacji.

Zanim dodasz kolejny kod, uruchom aplikację i kliknij ikonę wyszukiwania w prawym dolnym rogu ekranu. Powinno to spowodować wyświetlenie ekranu wyszukiwania bez żadnego przejścia.

499e1a677b4216bb.gif

Aby rozpocząć, znajdź metodę navigateToSearch w narzędziu MainActivity i dodaj ten fragment kodu przed wywołaniem metody NavController navigate, aby skonfigurować wyjście bieżącego fragmentu i ponownie wprowadzić MaterialSharedAxis przejścia na osi 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()
   }
}

Następnie dodaj do metody onCreate w klasie SearchFragment fragment kodu, który skonfiguruje przejścia wejścia i powrotu 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()
}

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

fragment_search.xml

android:transitionGroup="true"

Znakomicie. Teraz uruchom aplikację jeszcze raz i kliknij ikonę wyszukiwania. Ekrany widoku głównego i wyszukiwania powinny jednocześnie zanikać i zmieniać rozmiary wzdłuż osi Z, tworząc płynne przejście między tymi ekranami.

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. Ponieważ nie chcemy podkreślać relacji przestrzennej ani hierarchicznej, użyjemy zanikania, aby wykonać prostą „przemianę” między listami adresów e-mail.

Zanim dodasz kolejny kod, uruchom aplikację, dotknij logo Odpowiedz na dolnym pasku aplikacji i zmień skrzynki pocztowe. Lista adresów e-mail powinna się zmienić bez konieczności przenoszenia.

2c874c0a4588e8fb.gif

Na początek znajdź metodę navigateToHome w narzędziu MainActivity i dodaj ten fragment kodu przed wywołaniem metody NavController navigate w celu skonfigurowania przejścia 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 narzędziu onCreate ustaw dla parametru enterTransition fragmentu nowe wystąpienie MaterialFadeThrough.

HomeFragment.kt

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

Ponownie uruchom aplikację. Gdy otworzysz dolny panel nawigacji i zmienisz skrzynki pocztowe, bieżąca lista e-maili powinna zanikać i skalować w poziomie, a nowa lista zanika i skaluje się. Super!

f61dfd58ea7bd3fd.gif

8. Dodaj przejście z elementu z adresem e-mail na widok karty w ramach przekształcenia kontenera

W tym kroku dodasz przejście, które przekształci element w wyskakującą kartę. Używane jest tu przekształcenie kontenera, aby poinformować użytkownika, że działanie wykonane w wyskakującym okienku wpłynie na element, z którego pochodzi ono.

Zanim dodasz kod, uruchom aplikację Odpowiedź, kliknij e-maila, kliknij przycisk szybkiego działania „Odpowiedz”, a potem kliknij element kontaktowy odbiorcy. Element powinien zniknąć natychmiast, a na ekranie powinna pojawić się karta z adresami e-mail tego kontaktu bez animacji.

6200c682da2382d5.gif

W tym kroku będziesz pracować w domenie ComposeFragment. Do układu ComposeFragment dodano już elementy odbiorcy (domyślnie widoczne) oraz kartę odbiorcy (domyślnie niewidoczną). Element 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 zamienią widoczność recipientCardView i chip. Spowoduje to uruchomienie przekształcenia kontenera zarejestrowanego przez 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 uruchomisz teraz aplikację, element inteligentny powinien przekształcić się w kartę z adresami e-mail odbiorcy. Teraz skonfigurujemy przejście powrotne, aby zwinąć kartę z powrotem do elementu.

W metodzie collapseChip w pliku ComposeFragment dodaj podany niżej fragment kodu, aby złożyć kartę z powrotem w element układu.

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)

Ponownie uruchom aplikację. Kliknięcie elementu powinno rozwinąć element w kartę, a kliknięcie karty spowoduje zwinięcie karty z powrotem do elementu. Super!

e823b28e2890e05d.gif

9. Wszystko gotowe

Biblioteka MDC-Android, wykorzystująca mniej niż 100 wierszy kodu Kotlin i kilka podstawowych znaczników XML, pomogła stworzyć piękną przejścia w dotychczasowej aplikacji, która jest zgodna z wytycznymi Material Design, a także wygląda i działa spójnie na wszystkich urządzeniach z Androidem.

454a47ba96017a25.gif

Dalsze kroki

Więcej informacji o systemie animacji Material znajdziesz w specyfikacji i pełnej dokumentacji dla deweloperów. Dodaj do swojej aplikacji przejścia Material.

Dziękujemy za wypróbowanie ruchu Material Design. Mamy nadzieję, że to ćwiczenie z programowania Ci się podobało.

Udało mi się ukończyć to ćwiczenia z programowania w rozsądny sposób i w rozsądny sposób

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

Chcę nadal korzystać z systemu animacji Material Design

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