Компонент «Навигация» предоставляет простой и универсальный способ перехода к нужному месту. Этот интерфейс поддерживает широкий спектр контекстов и фреймворков пользовательского интерфейса. Например, компонент «Навигация» можно использовать с 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() .
Пример этого приведен в следующем подразделе.
Пример
В качестве иллюстрации к предыдущим разделам, обратите внимание на следующие моменты в приведенном ниже фрагменте:
- Каждый пункт назначения в графе создается с помощью маршрута, который представляет собой сериализуемый объект или класс, описывающий данные, необходимые для этого пункта назначения.
- Объект
MyAppNavHost, являющийся составным элементом, содержит экземплярNavController. - Соответственно, вызовы метода
navigate()должны происходить именно там, а не в более низкоуровневом компоненте, таком какProfileScreen. -
ProfileScreenесть кнопка, которая при нажатии переводит пользователя вFriendsList. Однако она сама не вызываетnavigate(). - Вместо этого кнопка вызывает функцию, которая предоставляется в качестве параметра в методе
onNavigateToFriends. - Когда
MyAppNavHostдобавляетProfileScreenв граф навигации, в методеonNavigateToFriendsпередается лямбда-функция, которая вызываетnavigate(route = FriendsList). - Это гарантирует, что при нажатии пользователем кнопки
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-фреймворком. Более подробную информацию об этих перегрузках см. в справочной документации.
Дополнительная информация
Для получения более подробной информации см. следующие страницы:
- Создайте контроллер навигации.
- Навигация и стек возврата
- Навигация с помощью параметров
- Типобезопасность в Kotlin DSL и Navigation Compose