Навигация к месту назначения

Компонент «Навигация» предоставляет простой и универсальный способ перехода к нужному месту. Этот интерфейс поддерживает широкий спектр контекстов и фреймворков пользовательского интерфейса. Например, компонент «Навигация» можно использовать с Compose, представлениями, фрагментами, активностями и даже пользовательскими фреймворками.

В этом руководстве описано, как использовать компонент «Навигация» для перехода к месту назначения в различных контекстах.

Используйте NavController

Для перемещения между пунктами назначения используется класс NavController . Дополнительную информацию о самом классе и способах создания его экземпляра см. в разделе «Создание контроллера навигации» . В этом руководстве подробно описано, как его использовать.

Независимо от используемого фреймворка пользовательского интерфейса, существует единственная функция, которую можно использовать для перехода к нужному месту: NavController.navigate() .

Для navigate() доступно множество перегрузок. Выбор перегрузки должен соответствовать конкретному контексту. Например, при переходе к составному объекту следует использовать одну перегрузку, а при переходе к представлению — другую.

В следующих разделах описаны некоторые ключевые перегрузки функции navigate() которые вы можете использовать.

Перейдите к составному элементу

Для перехода к составному объекту следует использовать NavController.navigate<T> . При использовании этой перегрузки navigate() принимает один аргумент route , которому вы передаете тип. Он служит ключом к месту назначения.

@Serializable
object FriendsList

navController.navigate(route = FriendsList)

Для перехода к составному объекту в графе навигации сначала определите свой NavGraph таким образом, чтобы каждый пункт назначения соответствовал определенному типу . Для составных объектов это делается с помощью функции composable() .

Предоставляйте доступ к событиям из ваших составных объектов.

Когда компонуемой функции необходимо перейти на новый экран, не следует передавать ей ссылку на NavController , чтобы она могла напрямую вызвать navigate() . В соответствии с принципами однонаправленного потока данных (UDF) , компонуемая функция должна вместо этого предоставлять событие, которое обрабатывает NavController .

Проще говоря, ваш компонент должен иметь параметр типа () -> Unit . При добавлении пунктов назначения в ваш NavHost с помощью функции composable() передайте вашему компоненту вызов NavController.navigate() .

Пример этого приведен в следующем подразделе.

Пример

В качестве иллюстрации к предыдущим разделам, обратите внимание на следующие моменты в приведенном ниже фрагменте:

  1. Каждый пункт назначения в графе создается с помощью маршрута, который представляет собой сериализуемый объект или класс, описывающий данные, необходимые для этого пункта назначения.
  2. Объект MyAppNavHost , являющийся составным элементом, содержит экземпляр NavController .
  3. Соответственно, вызовы метода navigate() должны происходить именно там, а не в более низкоуровневом компоненте, таком как ProfileScreen .
  4. ProfileScreen есть кнопка, которая при нажатии переводит пользователя в FriendsList . Однако она сама не вызывает navigate() .
  5. Вместо этого кнопка вызывает функцию, которая предоставляется в качестве параметра в методе onNavigateToFriends .
  6. Когда MyAppNavHost добавляет ProfileScreen в граф навигации, в методе onNavigateToFriends передается лямбда-функция, которая вызывает navigate(route = FriendsList ).
  7. Это гарантирует, что при нажатии пользователем кнопки ProfileScreen он корректно перейдет на 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")
    }
}

Для навигации используйте целочисленный идентификатор.

Для перехода к месту назначения с использованием целочисленного идентификатора вызовите перегрузку метода navigate(int) . Она принимает идентификатор ресурса либо действия, либо места назначения. Следующий фрагмент кода показывает, как можно использовать эту перегрузку для перехода к ViewTransactionsFragment :

Котлин

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

При навигации с использованием идентификаторов (ID) следует по возможности использовать действия (actions) . Действия предоставляют дополнительную информацию в навигационном графе, визуально показывая, как ваши пункты назначения связаны друг с другом.

Навигация с помощью NavDeepLinkRequest

Для перехода к неявной ссылке, содержащейся в библиотеке , используйте перегрузку метода navigate(NavDeepLinkRequest) . Следующий фрагмент кода демонстрирует реализацию этого метода:

Котлин

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)

В отличие от навигации с использованием идентификаторов действий или пунктов назначения, вы можете перейти по любой глубокой ссылке в вашем графе, независимо от того, виден ли пункт назначения. Вы можете перейти к пункту назначения в текущем графе или к пункту назначения в совершенно другом графе.

Действия и MIME-типы

Помимо Uri , NavDeepLinkRequest также поддерживает глубокие ссылки с действиями и MIME-типами. Чтобы добавить действие к запросу, используйте fromAction() или setAction() . Чтобы добавить MIME-тип к запросу, используйте fromMimeType() или setMimeType() .

Для корректного сопоставления запроса NavDeepLinkRequest с неявной ссылкой на целевой ресурс, URI, действие и MIME-тип должны совпадать с NavDeepLink в целевом ресурсе. URI должны соответствовать шаблону, действия должны точно совпадать, а MIME-типы должны быть связаны. Например, image/jpg соответствует image/\*

Дополнительные контексты

В этом документе описывается, как использовать NavController.navigate() в наиболее распространенных сценариях. Однако у этой функции есть ряд перегрузок, которые можно использовать в различных контекстах и ​​в сочетании с любым UI-фреймворком. Более подробную информацию об этих перегрузках см. в справочной документации.

Дополнительная информация

Для получения более подробной информации см. следующие страницы: