Zaprojektuj wykres nawigacyjny

Komponent Nawigacja korzysta z wykresu nawigacyjnego, który służy do zarządzania nawigacją w aplikacji. Wykres nawigacyjny to struktura danych obejmująca wszystkie miejsca docelowe w aplikacji i połączenia między nimi.

Typy miejsc docelowych

Istnieją 3 ogólne typy miejsc docelowych: hostowane, okno i aktywność. W tabeli poniżej przedstawiamy te 3 typy miejsc docelowych i ich przeznaczenie.

Typ

Opis

Przykłady zastosowań

Hostowane

Wypełnia cały host nawigacji. Oznacza to, że rozmiar hostowanego miejsca docelowego jest taki sam jak rozmiar hosta nawigacji, a poprzednie miejsca docelowe nie są widoczne.

Ekran główny i ekran ze szczegółami.

Dialog

Prezentuje komponenty interfejsu nakładki. Ten interfejs nie jest powiązany z lokalizacją hosta nawigacji ani jego rozmiarem. Pod miejscem docelowym będą widoczne poprzednie miejsca docelowe.

Alerty, wybory, formularze.

Aktywność

Reprezentuje unikalne ekrany lub funkcje aplikacji.

Pełni funkcję punktu wyjścia do wykresu nawigacyjnego, które uruchamia nowe działanie Androida, którym zarządza się niezależnie od komponentu Nawigacja.

We współczesnym programowaniu na Androida aplikacja składa się z jednej aktywności. Dlatego miejsca docelowe aktywności najlepiej sprawdzają się podczas interakcji z aktywnościami osób trzecich lub podczas procesu migracji.

Ten dokument zawiera przykłady hostowanych miejsc docelowych – najczęściej używanych i podstawowych miejsc docelowych. Informacje o innych miejscach docelowych znajdziesz w tych przewodnikach:

Platformy

Chociaż w każdym przypadku ten sam ogólny przepływ pracy ma zastosowanie, to sposób dokładnego tworzenia hosta i wykresu nawigacji zależy od używanej przez Ciebie platformy UI.

  • Tworzenie: użyj funkcji kompozycyjnej NavHost. Dodaj do niego NavGraph, korzystając z DSL Kotlin. Wykres możesz utworzyć na 2 sposoby:
    • W ramach NavHost: podczas dodawania NavHost utwórz wykres nawigacyjny bezpośrednio.
    • Automatycznie: użyj metody NavController.createGraph(), aby utworzyć dokument NavGraph i przekazać go bezpośrednio do NavHost.
  • Fragmenty: jeśli używasz fragmentów z platformą Widoki UI, jako hosta użyj NavHostFragment. Wykres nawigacyjny można utworzyć na kilka sposobów:
    • Automatyzacja: użyj DSL Kotlin, aby utworzyć NavGraph i bezpośrednio zastosować go do NavHostFragment.
      • Funkcja createGraph() używana w przypadku DSL Kotlin zarówno w przypadku fragmentów, jak i tworzenia jest taka sama.
    • XML:zapisz host i wykres nawigacji bezpośrednio w formacie XML.
    • Edytor Android Studio: użyj edytora graficznego w Android Studio, aby utworzyć i dostosować wykres jako plik zasobów XML.

Utwórz

W narzędziu Compose użyj obiektu lub klasy możliwej do serializacji, aby zdefiniować trasę. Trasa zawiera informacje o tym, jak dotrzeć do celu, oraz wszystkie niezbędne informacje. Po zdefiniowaniu tras użyj funkcji NavHost kompozycyjnej, aby utworzyć wykres nawigacyjny. Przeanalizuj ten przykład:

@Serializable
object Profile
@Serializable
object FriendsList

val navController = rememberNavController()

NavHost(navController = navController, startDestination = Profile) {
    composable<Profile> { ProfileScreen( /* ... */ ) }
    composable<FriendsList> { FriendsListScreen( /* ... */ ) }
    // Add more destinations similarly.
}
  1. Obiekt możliwe do serializowania reprezentuje każdą z 2 tras: Profile i FriendsList.
  2. Wywołanie funkcji kompozycyjnej NavHost przekazuje NavController i trasę miejsca docelowego początkowego.
  3. Funkcja lambda przekazana do interfejsu NavHost ostatecznie wywołuje metodę NavController.createGraph() i zwraca NavGraph.
  4. Każda trasa jest podawana jako argument typu NavGraphBuilder.composable<T>(), który dodaje miejsce docelowe do wynikowego argumentu NavGraph.
  5. Funkcja lambda przekazana do composable jest tym, co wyświetla NavHost w przypadku tego miejsca docelowego.

Czym jest lambda

Aby lepiej zrozumieć funkcję lambda, która tworzy NavGraph, rozważ utworzenie tego samego wykresu co w poprzednim fragmencie kodu. Możesz utworzyć parametr NavGraph oddzielnie za pomocą funkcji NavController.createGraph() i przekazać go bezpośrednio do interfejsu NavHost:

val navGraph by remember(navController) {
  navController.createGraph(startDestination = Profile)) {
    composable<Profile> { ProfileScreen( /* ... */ ) }
    composable<FriendsList> { FriendsListScreen( /* ... */ ) }
  }
}
NavHost(navController, navGraph)

Argumenty przekazywania

Jeśli musisz przekazywać dane do miejsca docelowego, zdefiniuj trasę za pomocą klasy z parametrami. Na przykład trasa Profile to klasa danych z parametrem name.

@Serializable
data class Profile(val name: String)

Za każdym razem, gdy musisz przekazać argumenty do tego miejsca docelowego, tworzysz instancję klasy trasy, która przekazuje argumenty do konstruktora klas.

Uzyskiwanie instancji trasy

Instancję trasy możesz uzyskać za pomocą NavBackStackEntry.toRoute() lub SavedStateHandle.toRoute(). Gdy tworzysz miejsce docelowe za pomocą właściwości composable(), jako parametr dostępny jest NavBackStackEntry.

@Serializable
data class Profile(val name: String)

val navController = rememberNavController()

NavHost(navController = navController, startDestination = Profile(name="John Smith")) {
    composable<Profile> { backStackEntry ->
        val profile: Profile = backStackEntry.toRoute()
        ProfileScreen(name = profile.name) }
}

Zwróć uwagę na te kwestie:

  • Trasa Profile określa początkowe miejsce docelowe na wykresie nawigacyjnym przy użyciu elementu "John Smith" jako argumentu name.
  • Miejsce docelowe to blok composable<Profile>{}.
  • Funkcja kompozycyjna ProfileScreen przyjmuje wartość profile.name dla własnego argumentu name.
  • Dlatego wartość "John Smith" jest przekazywana do ProfileScreen.

Minimalny przykład

Pełen przykład współdziałania elementów NavController i NavHost:

@Serializable
data class Profile(val name: String)

@Serializable
object FriendsList

// Define the ProfileScreen composable.
@Composable
fun ProfileScreen(
    profile: Profile
    onNavigateToFriendsList: () -> Unit,
  ) {
  Text("Profile for ${profile.name}")
  Button(onClick = { onNavigateToFriendsList() }) {
    Text("Go to Friends List")
  }
}

// Define the FriendsListScreen composable.
@Composable
fun FriendsListScreen(onNavigateToProfile: () -> Unit) {
  Text("Friends List")
  Button(onClick = { onNavigateToProfile() }) {
    Text("Go to Profile")
  }
}

// Define the MyApp composable, including the `NavController` and `NavHost`.
@Composable
fun MyApp() {
  val navController = rememberNavController()
  NavHost(navController, startDestination = Profile(name = "John Smith")) {
    composable<Profile> { backStackEntry ->
        val profile: Profile = backStackEntry.toRoute()
        ProfileScreen(
            profile = profile,
            onNavigateToFriendsList = {
                navController.navigate(route = FriendsList)
            }
        )
    }
    composable<FriendsList> {
      FriendsListScreen(
        onNavigateToProfile = {
          navController.navigate(
            route = Profile(name = "Aisha Devi")
          )
        }
      )
    }
  }
}

Jak widać we fragmencie kodu, zamiast przekazywać zdarzenie NavController do funkcji kompozycyjnej, ujawnij zdarzenie w interfejsie NavHost. Oznacza to, że obiekty kompozycyjne powinny mieć parametr typu () -> Unit, dla którego obiekt NavHost przekazuje parametr lambda wywołujący NavController.navigate().

Fragmenty

Jak wspomnieliśmy w poprzednich sekcjach, używając fragmentów, można automatycznie utworzyć wykres nawigacyjny automatycznie za pomocą edytora Kotlin DSL, XML lub edytora Android Studio.

W sekcjach poniżej szczegółowo opisujemy poszczególne podejścia.

Automatycznie

DSL Kotlin umożliwia zautomatyzowane tworzenie wykresu nawigacyjnego z fragmentami. Pod wieloma względami jest to bardziej eleganckie i nowoczesne niż korzystanie z pliku zasobów XML.

Przyjrzyjmy się przykładowi, w którym zaimplementowano dwuekranowy wykres nawigacyjny.

Najpierw musisz utworzyć obiekt NavHostFragment, który nie może zawierać elementu app:navGraph:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>

Następnie przekaż id (NavHostFragment) maszynie wirtualnej NavController.findNavController. Powiąże to kontroler nawigacji z elementem NavHostFragment.

Następnie wywołanie NavController.createGraph() łączy wykres z tabelą NavController, a tym samym z tabelą NavHostFragment:

@Serializable
data class Profile(val name: String)

@Serializable
object FriendsList

// Retrieve the NavController.
val navController = findNavController(R.id.nav_host_fragment)

// Add the graph to the NavController with `createGraph()`.
navController.graph = navController.createGraph(
    startDestination = Profile(name = "John Smith")
) {
    // Associate each destination with one of the route constants.
    fragment<ProfileFragment, Profile> {
        label = "Profile"
    }

    fragment<FriendsListFragment, FriendsList>() {
        label = "Friends List"
    }

    // Add other fragment destinations similarly.
}

Używanie DSL w ten sposób jest bardzo podobne do procedury opisanej w poprzedniej sekcji dotyczącej tworzenia. Na przykład zarówno w tym miejscu, jak i w tym miejscu funkcja NavController.createGraph() generuje NavGraph. I podobnie, NavGraphBuilder.composable() dodaje do wykresu miejsca docelowe kompozycyjne, tutaj NavGraphBuilder.fragment() dodaje miejsce docelowe fragmentu.

Więcej informacji o korzystaniu z DSL Kotlin znajdziesz w artykule Tworzenie wykresu przy użyciu DSL NavGraphBuilder.

XML

Kod XML możesz zapisać bezpośrednio. Poniżej znajduje się przykład, który jest odpowiednikiem dwuekranowego przykładu z poprzedniej sekcji.

Najpierw utwórz NavHostFragment. Służy jako host nawigacji, który zawiera rzeczywisty wykres nawigacyjny.

Minimalna implementacja NavHostFragment:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:navGraph="@navigation/nav_graph" />

</FrameLayout>

NavHostFragment zawiera atrybut app:navGraph. Użyj tego atrybutu, aby połączyć wykres nawigacyjny z hostem nawigacji. Oto przykład implementacji wykresu:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_graph"
    app:startDestination="@id/profile">

    <fragment
        android:id="@+id/profile"
        android:name="com.example.ProfileFragment"
        android:label="Profile">

        <!-- Action to navigate from Profile to Friends List. -->
        <action
            android:id="@+id/action_profile_to_friendslist"
            app:destination="@id/friendslist" />
    </fragment>

    <fragment
        android:id="@+id/friendslist"
        android:name="com.example.FriendsListFragment"
        android:label="Friends List" />

    <!-- Add other fragment destinations similarly. -->
</navigation>

Do definiowania połączeń między różnymi miejscami docelowymi służą działania. W tym przykładzie fragment profile zawiera działanie powodujące przejście do adresu friendslist. Więcej informacji znajdziesz w artykule Używanie działań i fragmentów nawigacji.

Edytujący

Wykresem nawigacyjnym aplikacji możesz zarządzać za pomocą edytora nawigacji w Android Studio. Jest to w zasadzie GUI, którego można użyć do tworzenia i edytowania kodu XML NavigationFragment, tak jak to pokazano w poprzedniej sekcji.

Więcej informacji znajdziesz w artykule Edytor nawigacji.

Zagnieżdżone wykresy

Możesz też używać zagnieżdżonych wykresów. Wiąże się to z wykorzystaniem wykresu jako miejsca docelowego nawigacji. Więcej informacji znajdziesz w artykule Wykresy zagnieżdżone.

Dalsza lektura

Więcej podstawowych pojęć związanych z nawigacją znajdziesz w tych przewodnikach: