Nawigacja do miejsca docelowego

Komponent Navigation zapewnia prosty i ogólny sposób nawigowania do miejsca docelowego. Ten interfejs obsługuje różne konteksty i platformy interfejsu. Możesz na przykład używać komponentu Navigation z Compose, widokami, fragmentami, aktywnościami, a nawet niestandardowymi platformami interfejsu.

Z tego przewodnika dowiesz się, jak używać komponentu Navigation do nawigowania do miejsca docelowego w różnych kontekstach.

Używanie NavController

Kluczowym typem używanym do przechodzenia między miejscami docelowymi jest NavController. Więcej informacji o samej klasie i sposobie tworzenia jej instancji znajdziesz w artykule Tworzenie kontrolera nawigacji. Z tego przewodnika dowiesz się, jak go używać.

Niezależnie od tego, której platformy interfejsu używasz, do nawigowania do miejsca docelowego możesz użyć jednej funkcji: NavController.navigate().

Dostępnych jest wiele przeciążeń funkcji navigate(). Przeciążenie, którego należy użyć, odpowiada dokładnemu kontekstowi. Na przykład, gdy nawigujesz do elementu kompozycyjnego, używasz jednego przeciążenia, a gdy nawigujesz do widoku – innego.

W sekcjach poniżej opisujemy niektóre z najważniejszych przeciążeń funkcji navigate(), których możesz używać.

Nawigowanie do elementu kompozycyjnego

Aby nawigować do elementu kompozycyjnego, użyj funkcji NavController.navigate<T>. W przypadku tego przeciążenia funkcja navigate() przyjmuje 1 argument route, dla którego przekazujesz typ. Służy on jako klucz do miejsca docelowego.

@Serializable
object FriendsList

navController.navigate(route = FriendsList)

Aby nawigować do elementu kompozycyjnego na wykresie nawigacji, najpierw zdefiniuj swój NavGraph tak, aby każde miejsce docelowe odpowiadało typowi. W przypadku elementów kompozycyjnych robisz to za pomocą funkcji composable().

Udostępnianie zdarzeń z funkcji kompozycyjnych

Gdy funkcja typu „composable” musi przejść do nowego ekranu, nie należy przekazywać jej odniesienia do NavController, aby mogła bezpośrednio wywołać navigate(). Zgodnie z zasadami jednokierunkowego przepływu danych (UDF) element kompozycyjny powinien zamiast tego udostępniać zdarzenie, które obsługuje NavController.

Mówiąc wprost, element kompozycyjny powinien mieć parametr typu () -> Unit. Gdy dodajesz miejsca docelowe do NavHost za pomocą funkcji composable(), przekaż do elementu kompozycyjnego wywołanie NavController.navigate().

Przykład znajdziesz w podsekcji poniżej.

Przykład

Aby zademonstrować informacje z poprzednich sekcji, zwróć uwagę na te punkty w poniższym fragmencie kodu:

  1. Każde miejsce docelowe na wykresie jest tworzone za pomocą trasy, która jest obiektem lub klasą z możliwością serializacji opisującą dane wymagane przez to miejsce docelowe.
  2. Element kompozycyjny MyAppNavHost zawiera instancję NavController.
  3. W związku z tym wywołania navigate() powinny występować w tym miejscu, a nie w niższym elemencie kompozycyjnym, takim jak ProfileScreen.
  4. ProfileScreen zawiera przycisk, który po kliknięciu przenosi użytkownika do FriendsList. Nie wywołuje on jednak samodzielnie funkcji navigate().
  5. Zamiast tego przycisk wywołuje funkcję, która jest udostępniana jako parametr onNavigateToFriends.
  6. Gdy MyAppNavHost dodaje ProfileScreen do wykresu nawigacji, w przypadku onNavigateToFriends przekazuje lambdę, która wywołuje navigate(route = FriendsList).
  7. Dzięki temu, gdy użytkownik naciśnie przycisk ProfileScreen, zostanie prawidłowo przeniesiony do FriendsListScreen.
@Serializable
object Profile
@Serializable
object FriendsList

@Composable
fun MyAppNavHost(
    modifier: Modifier = Modifier,
    navController: NavHostController = rememberNavController(),
) {
    NavHost(
        modifier = modifier,
        navController = navController,
        startDestination = Profile
    ) {
        composable<Profile> {
            ProfileScreen(
                onNavigateToFriends = { navController.navigate(route = FriendsList) },
                /*...*/
            )
        }
        composable<FriendsList> { FriendsListScreen(/*...*/) }
    }
}

@Composable
fun ProfileScreen(
    onNavigateToFriends: () -> Unit,
    /*...*/
) {
    /*...*/
    Button(onClick = onNavigateToFriends) {
        Text(text = "See friends list")
    }
}

Nawigowanie za pomocą identyfikatora liczby całkowitej

Aby nawigować do miejsca docelowego za pomocą identyfikatora liczby całkowitej, wywołaj navigate(int) przeciążenie. Przyjmuje ono identyfikator zasobu działania lub miejsca docelowego. Poniższy fragment kodu pokazuje, jak użyć tego przeciążenia do nawigowania do ViewTransactionsFragment:

Kotlin

viewTransactionsButton.setOnClickListener { view ->
  view.findNavController().navigate(R.id.viewTransactionsAction)
}

Java

viewTransactionsButton.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View view) {
      Navigation.findNavController(view).navigate(R.id.viewTransactionsAction);
  }
});

Podczas nawigowania za pomocą identyfikatorów, jeśli to możliwe, używaj działań. Działania zawierają dodatkowe informacje na wykresie nawigacji, wizualnie pokazując, jak miejsca docelowe są ze sobą połączone.

Nawigowanie za pomocą NavDeepLinkRequest

Aby nawigować do miejsca docelowego z niejawnym precyzyjnym linkiem, użyj navigate(NavDeepLinkRequest) przeciążenia. Poniższy fragment kodu zawiera implementację tej metody:

Kotlin

val request = NavDeepLinkRequest.Builder
  .fromUri("android-app://androidx.navigation.app/profile".toUri())
  .build()
findNavController().navigate(request)

Java

NavDeepLinkRequest request = NavDeepLinkRequest.Builder
  .fromUri(Uri.parse("android-app://androidx.navigation.app/profile"))
  .build()
NavHostFragment.findNavController(this).navigate(request)

W przeciwieństwie do nawigacji za pomocą identyfikatorów działań lub miejsc docelowych możesz nawigować do dowolnego precyzyjnego linku na wykresie, niezależnie od tego, czy miejsce docelowe jest widoczne. Możesz nawigować do miejsca docelowego na bieżącym grafie lub do miejsca docelowego na zupełnie innym grafie.

Działania i typy MIME

Oprócz Uri NavDeepLinkRequest obsługuje też precyzyjne linki z działaniami i typami MIME. Aby dodać działanie do żądania, użyj fromAction() lub setAction(). Aby dodać typ MIME do żądania, użyj fromMimeType() lub setMimeType().

Aby NavDeepLinkRequest prawidłowo pasował do miejsca docelowego z precyzyjnym linkiem typu implicit, identyfikator URI, działanie i typ MIME muszą pasować do NavDeepLink w miejscu docelowym. Identyfikatory URI muszą pasować do wzorca, działania muszą być dokładnie takie same, a typy MIME muszą być powiązane. Na przykład image/jpg pasuje do image/\*.

Dodatkowe konteksty

W tym dokumencie opisujemy, jak używać funkcji NavController.navigate() w najczęstszych przypadkach użycia. Funkcja ta ma jednak wiele przeciążeń, których możesz używać w różnych kontekstach i w połączeniu z dowolną platformą interfejsu. Więcej informacji o tych przeciążeniach znajdziesz w dokumentacji referencyjnej.

Więcej informacji

Więcej informacji znajdziesz na tych stronach: