Android Architecture Components: Navigation — zagadnienia zaawansowane

Jest to cykl artykułów poświęcony komponentom architektury Androida. Wszystkie artykuły znajdziesz na tej stronie.

Omówiliśmy już podstawy biblioteki Navigation. W tym artykule przyjrzymy się innym funkcją, które oferuje.

Dodawanie przejść

Możesz dodać niestandardowe animacje do akcji. W tym celu otwórz swój wykres i dodaj następujące atrybuty do akcji:

app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
app:popExitAnim="@anim/nav_default_pop_exit_anim"

Każdy z tagów definiuje przejście dla jednego z przypadków:

  • enterAnim — animacja, która ma zostać użyta, gdy otwieramy miejsca docelowe.
  • exitAnim — animacja, która ma być używana, gdy opuszczamy miejsca docelowe.
  • popEnterAnim animacja, która ma być używana, gdy miejsce docelowe jest przenoszone na górną część stosu.
  • popExitAnim animacja, która ma być używana, gdy miejsce docelowe jest przenoszone na dalszą pozycję w stosie.

Każda animacja, której chcesz użyć, musi być zdefiniowana we własnym pliku zasobów animacji, w katalogu „res/anim”. Jeśli Twój projekt nie zawiera jeszcze tego katalogu, musisz go utworzyć. A jak może wyglądać przykładowa animacja? Ano tak:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromYDelta="0%"
        android:toYDelta="-100%"
        android:duration="1500">
    </translate>
</set>

Przejścia można również zdefiniować programowo za pomocą instancji NavOptions.Builder:

    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_list_news, container, false);
      ...
        NavOptions navOptions = new NavOptions.Builder()
                .setEnterAnim(R.anim.nav_default_enter_anim)
                .setExitAnim(R.anim.nav_default_exit_anim)
                .setPopEnterAnim(R.anim.nav_default_pop_enter_anim)
                .setPopExitAnim(R.anim.nav_default_pop_exit_anim)
                .build();
       list.setOnItemClickListener((adapterView, view1, position, id) -> {
            Bundle args = new Bundle();
            args.putInt("idNews", position);
           // Navigation.findNavController(view).navigate(R.id.goToDetails, args);
            Navigation.findNavController(view1).navigate(R.id.goToDetails, null, navOptions);
        });
        return view;
    }

Uzupełnij wiedze o: Task i Back Stack w Androidzie

Zagnieżdżone wykresy

Wraz z rozwojem aplikacji o nowe możliwości, a co za tym idzie, powstają nowe aktywności, fragmenty. W pewnym momencie jeden wykres nie wystarcza. Może zdarzyć się sytuacja, w której chcesz pogrupować pewne części. Na przykład masz aplikację, w której masz funkcje darmowe i płatne. Chcesz pogrupować wykres na część darmową i premium. Do tego właśnie przydadzą się zagnieżdżone wykresy. Aby to uczynić, Twój wykres może przybrać taką formę:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    app:startDestination="@id/listNews">
    <fragment
        android:id="@+id/listNews"
        android:name="net.myenv.architecturecomponents.Navigation.ListNews"
        android:label="News"
        tools:layout="@layout/fragment_list_news">
        <action
            android:id="@+id/goToDetails"
            app:destination="@id/details" />
        <action
            android:id="@+id/premium_articles"
            app:destination="@id/details" />
    </fragment>
    <fragment
        android:id="@+id/details"
        android:name="net.myenv.architecturecomponents.Navigation.Details"
        android:label="Details" />
    <navigation android:id="@+id/content_premium" app:startDestination="@id/premium_articles"
    <fragment android:id="@+id/readLeter"
        android:label="Read leter"
        android:name="net.myenv.architecturecomponents.Navigation.ReadLeter"
        tools:layout="@layout/fragment_read_leter"/>
    <fragment android:id="@+id/premium_articles"
        android:label="Premium Articles"
        android:name="net.myenv.architecturecomponents.Navigation.PremiumArticles"
        tools:layout="@layout/fragment_premium_articles"/>
    </navigation>
</navigation>

Oczywiście możemy część premium przenieść do osobnego pliku i wtedy w głównym wykresie dodać znacznik include.

 <include app:graph="@navigation/premium_graph" />

Warunkowa nawigacja

Może zdarzyć się tak, że potrzebujesz przekierować użytkownika do pewnego ekranu w zależności od spełnienia jakiegoś warunku. Kontynuując nasz przykład z poprzednich artykułów — posiadamy aplikację z artykułami. Jeżeli użytkownik posiada zapisane artykuły, to przekieruj go do odpowiedniego ekranu. W przeciwnym wypadku przekieruj użytkownika do wyszukiwarki artykułów. Nasz kod może wyglądać wtedy tak:

if (hasFavorites())
    destination = R.id.action_Favorites;
else
    destination = R.id.action_Search;
Navigation.findNavController(this, destination).navigateUp();

Nie zapomnij dodać odpowiednich akcji do wykresu we fragmencie ListNews (zobacz poprzedni wpis).

Opcjonalnie możemy dodać trzeci argument do funkcji navigate(). Określa on opcję nawigacji. W naszym przypadku czyści tylny ston, aby uniemożliwić użytkownikowi powrót do fragmentu ListNews.

NavOptions.Builder().setPopUpTo(R.id.listNews,true).build();

W tym przypadku mamy tylko jedno miejsce docelowe i musimy je także wyczyścić. Zatem ustawimy parametr inclusive na true.

Bardziej zaawansowany przykład możesz znaleźć tutaj.

Głębokie linkowanie

O linkowaniu już pisałem na blogu. Możesz zapoznać się z tym artykułem pod tym adresem. Zapoznałeś się z nim? Ok to ruszamy dalej.

Głębokie linki to adresy URL, które prowadzą do określonego ekranu lub zawartości w Twojej aplikacji. Aby korzystać z tej możliwości w bibliotece Navigation, musimy dodać odpowiedni wpis do naszego wykresu. Załóżmy, że chcemy bezpośredni link do fragmentu ReadLeter. Kod może wyglądać następująco:

  <fragment android:id="@+id/readLeter"
        android:label="Read leter"
        android:name="net.myenv.architecturecomponents.Navigation.ReadLeter"
        tools:layout="@layout/fragment_read_leter">
        <deepLink
            android:id="@+id/deepLink"
            app:uri="https://www.myenv.net/readLeter"
             />
    </fragment>

Aby włączyć niejawne głębokie linkowanie, musisz dodać wpis do manifestu aplikacji.

<activity name=".MainActivity" ...>
     ...
     <nav-graph android:value="@navigation/basic_navigation" />
     ...
 </activity>

Co dalej?

  • Polub stronę MYENV na Facebooku oraz śledź mnie na Twitterze
  • Zachęcam do komentowania i pisania propozycji tematów, o których chcesz przeczytać
  • Poleć ten wpis za pomocą poniższych przycisków. Będę Ci za to bardzo wdzięczny 🙂
  • Życzę Ci miłego dnia i miłego kodowania 🙂