Компонент «Навигация» использует граф навигации для управления навигацией вашего приложения. Граф навигации — это структура данных, которая содержит все пункты назначения в вашем приложении и связи между ними.
Типы пунктов назначения
Существует три основных типа мест назначения: размещенное, диалоговое и действие. В следующей таблице описаны эти три типа назначения и их назначение.
Тип | Описание | Варианты использования |
---|---|---|
Хостинг | Заполняет весь хост навигации. То есть размер размещенного пункта назначения такой же, как размер узла навигации, а предыдущие пункты назначения не видны. | Главный и подробный экраны. |
Диалог | Представляет наложение компонентов пользовательского интерфейса. Этот пользовательский интерфейс не привязан к местоположению узла навигации или его размеру. Предыдущие пункты назначения отображаются под пунктом назначения. | Оповещения, выборки, формы. |
Активность | Представляет уникальные экраны или функции приложения. | Служить точкой выхода для графа навигации, который запускает новое действие Android, управляемое отдельно от компонента навигации. В современной разработке Android приложение состоит из одного действия. Поэтому места назначения действий лучше всего использовать при взаимодействии с действиями третьих лиц или в рамках процесса миграции . |
Этот документ содержит примеры размещенных направлений, которые являются наиболее распространенными и фундаментальными. Информацию о других направлениях смотрите в следующих руководствах:
Рамки
Хотя в каждом случае применяется один и тот же общий рабочий процесс, то, как именно вы создаете узел навигации и график, зависит от используемой вами инфраструктуры пользовательского интерфейса.
- Составление: используйте составной элемент
NavHost
. Добавьте к немуNavGraph
с помощью Kotlin DSL . Создать график можно двумя способами:- Как часть NavHost: создайте граф навигации непосредственно в рамках добавления
NavHost
. - Программно: используйте метод
NavController.createGraph()
, чтобы создатьNavGraph
и передать его напрямую вNavHost
.
- Как часть NavHost: создайте граф навигации непосредственно в рамках добавления
- Фрагменты. При использовании фрагментов с платформой пользовательского интерфейса представлений используйте
NavHostFragment
в качестве узла. Существует несколько способов создания навигационного графа:- Программно: используйте Kotlin DSL для создания
NavGraph
и непосредственного применения его кNavHostFragment
.- Функция
createGraph()
, используемая с Kotlin DSL как для фрагментов, так и для Compose, одинакова.
- Функция
- XML: напишите свой навигационный хост и график непосредственно в XML.
- Редактор Android Studio: используйте редактор графического интерфейса в Android Studio, чтобы создать и настроить график в виде файла ресурсов XML.
- Программно: используйте Kotlin DSL для создания
Сочинить
В Compose используйте сериализуемый объект или класс для определения маршрута . Маршрут описывает, как добраться до пункта назначения, и содержит всю информацию, необходимую для пункта назначения. После того, как вы определили свои маршруты, используйте компонуемый NavHost
для создания навигационного графа. Рассмотрим следующий пример:
@Serializable
object Profile
@Serializable
object FriendsList
val navController = rememberNavController()
NavHost(navController = navController, startDestination = Profile) {
composable<Profile> { ProfileScreen( /* ... */ ) }
composable<FriendsList> { FriendsListScreen( /* ... */ ) }
// Add more destinations similarly.
}
- Сериализуемый объект представляет каждый из двух маршрутов:
Profile
иFriendsList
. - Вызов компонуемого
NavHost
передаетNavController
и маршрут для начального пункта назначения. - Лямбда, передаваемая в
NavHost
в конечном итоге вызываетNavController.createGraph()
и возвращаетNavGraph
. - Каждый маршрут предоставляется в качестве аргумента типа функции
NavGraphBuilder.composable<T>()
которая добавляет пункт назначения к результирующемуNavGraph
. - Лямбда, передаваемая в
composable
— это то, чтоNavHost
отображает для этого места назначения.
Понять лямбду
Чтобы лучше понять лямбду, создающую NavGraph
, учтите, что для построения того же графика, что и в предыдущем фрагменте кода, вы можете создать NavGraph
отдельно с помощью NavController.createGraph()
и передать его непосредственно в NavHost
:
val navGraph by remember(navController) {
navController.createGraph(startDestination = Profile)) {
composable<Profile> { ProfileScreen( /* ... */ ) }
composable<FriendsList> { FriendsListScreen( /* ... */ ) }
}
}
NavHost(navController, navGraph)
Передача аргументов
Если вам нужно передать данные в пункт назначения, определите маршрут с помощью класса, имеющего параметры. Например, маршрут Profile
— это класс данных с параметром name
.
@Serializable
data class Profile(val name: String)
Всякий раз, когда вам нужно передать аргументы в этот пункт назначения, вы создаете экземпляр класса маршрута, передавая аргументы конструктору класса.
Для необязательных аргументов создайте поля, допускающие значение NULL, со значением по умолчанию.
@Serializable
data class Profile(val nickname: String? = null)
Получить экземпляр маршрута
Вы можете получить экземпляр маршрута с помощью NavBackStackEntry.toRoute()
или SavedStateHandle.toRoute()
. Когда вы создаете пункт назначения с помощью composable()
, 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) }
}
Обратите внимание на следующее в этом фрагменте:
- Маршрут
Profile
указывает начальный пункт назначения в графе навигации с"John Smith"
в качестве аргументаname
. - Сам пункт назначения — это
composable<Profile>{}
. - Компонуемый
ProfileScreen
принимает значениеprofile.name
в качестве собственного аргументаname
. - Таким образом, значение
"John Smith"
передается вProfileScreen
.
Минимальный пример
Полный пример совместной работы NavController
и 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")
)
}
)
}
}
}
Как показано во фрагменте, вместо передачи NavController
вашим компонуемым объектам необходимо предоставить событие NavHost
. То есть ваши составные элементы должны иметь параметр типа () -> Unit
, для которого NavHost
передает лямбду, вызывающую NavController.navigate()
.
Фрагменты
Как указано в предыдущих разделах, при использовании фрагментов у вас есть возможность создать граф навигации программно с помощью Kotlin DSL, XML или редактора Android Studio.
В следующих разделах подробно описаны эти различные подходы.
Программно
Kotlin DSL предоставляет программный способ создания навигационного графа с фрагментами. Во многих отношениях это проще и современнее, чем использование файла ресурсов XML.
Рассмотрим следующий пример, в котором реализуется двухэкранный граф навигации.
Сначала необходимо создать NavHostFragment
, который не должен включать элемент 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>
Затем передайте id
NavHostFragment
в NavController.findNavController
. Это связывает NavController с NavHostFragment
.
Впоследствии вызов NavController.createGraph()
связывает график с NavController
и, следовательно, с 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.
}
Использование DSL таким образом очень похоже на рабочий процесс, описанный в предыдущем разделе Compose . Например, и там, и здесь функция NavController.createGraph()
генерирует NavGraph
. Аналогично, в то время как NavGraphBuilder.composable()
добавляет в граф компонуемые пункты назначения, здесь NavGraphBuilder.fragment()
добавляет пункт назначения фрагмента.
Дополнительные сведения о том, как использовать Kotlin DSL, см. в разделе Построение графика с помощью NavGraphBuilder DSL .
XML
Вы можете написать XML самостоятельно. Следующий пример отражает и эквивалентен примеру с двумя экранами из предыдущего раздела.
Сначала создайте NavHostFragment
. Он служит хостом навигации, содержащим фактический граф навигации.
Минимальная реализация 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
содержит атрибут app:navGraph
. Используйте этот атрибут для подключения графа навигации к узлу навигации. Ниже приведен пример того, как можно реализовать график:
<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>
Вы используете действия для определения связей между различными пунктами назначения. В этом примере фрагмент profile
содержит действие, которое осуществляет переход к friendslist
. Дополнительные сведения см. в разделе Использование действий и фрагментов навигации .
Редактор
Вы можете управлять графиком навигации вашего приложения с помощью редактора навигации в Android Studio. По сути, это графический интерфейс, который вы можете использовать для создания и редактирования XML-файла NavigationFragment
, как показано в предыдущем разделе.
Дополнительную информацию см. в разделе Редактор навигации .
Вложенные графики
Вы также можете использовать вложенные графики. Это предполагает использование графика в качестве пункта назначения навигации. Дополнительные сведения см. в разделе Вложенные графики .
Дальнейшее чтение
Дополнительные сведения об основных концепциях навигации см. в следующих руководствах:
- Обзор : обязательно прочтите общий обзор компонента навигации.
- Направления действий : примеры реализации мест назначения, которые перенаправляют пользователя к действиям.
- Пункты назначения диалога : примеры создания пунктов назначения, которые перенаправляют пользователя в диалог.
- Навигация к пункту назначения : подробное руководство, описывающее, как перемещаться от одного пункта назначения к другому.
- Вложенные графики : подробное руководство о том, как вложить один навигационный график в другой.