The Navigation component provides a straightforward and generic way of navigating to a destination. This interface supports a range of contexts and UI frameworks. For example, you can use the Navigation component with Compose, views, fragments, activities, and even custom UI frameworks.
This guide describes how you can use the Navigation component to navigate to a destination in various contexts.
Use a NavController
The key type you use to move between destinations is the NavController
. See Create a navigation controller for more information on the class itself and how to create an instance of it. This guide details how to use it.
Navigate
Regardless of which UI framework you use, there is a single function you can use to navigate to a destination: NavController.navigate()
.
There are many overloads available for navigate()
. The overload you should choose corresponds to your exact context. For example, you should use one overload when navigating to a composable and another when navigating to a view.
The following sections outline some of the key navigate()
overloads you can use.
Navigate to a composable
To navigate to a composable, you should use NavController.navigate<T>
. With this overload, navigate()
takes a single route
argument for which you pass a type. It serves as the key to a destination.
@Serializable
object FriendsList
navController.navigate(route = FriendsList)
To navigate to a composable in the navigation graph, first define your NavGraph
such that each destination corresponds to a type. For composables, you do so with the composable()
function.
Expose events from your composables
When a composable function needs to navigate to a new screen, you shouldn't pass it a reference to the NavController
so that it can call navigate()
directly. According to Unidirectional Data Flow (UDF) principles, the composable should instead expose an event that the NavController
handles.
More directly put, your composable should have a parameter of type () -> Unit
. When you add destinations to your NavHost
with the composable()
function, pass your composable a call to NavController.navigate()
.
See the following subsection for an example of this.
Example
As a demonstration of the preceding sections, observe these points in the following snippet:
- Each destination in the graph is created using a route, which is a serializable object or class describing the data required by that destination.
- The
MyAppNavHost
composable holds theNavController
instance. - Accordingly, calls to
navigate()
should occur there and not in a lower composable likeProfileScreen
. ProfileScreen
contains a button that navigates the user toFriendsList
when clicked. However, it does not callnavigate()
itself.- Instead, the button calls a function that is exposed as the parameter
onNavigateToFriends
. - When
MyAppNavHost
addsProfileScreen
to the navigation graph, foronNavigateToFriends
it passes a lambda that callsnavigate(route = FriendsList
). - This ensures that when the user presses the button
ProfileScreen
, they navigate correctly toFriendsListScreen
.
@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 using integer ID
To navigate to a destination using an integer ID, call the navigate(int)
overload. It takes the resource ID of either an action or a destination. The following code snippet shows how you can use this overload to navigate to the 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);
}
});
When navigating using IDs, you should use actions where possible. Actions provide additional information in your navigation graph, visually showing how your destinations connect to each other.
Navigate using NavDeepLinkRequest
To navigate to an implicit deep link destination, use the navigate(NavDeepLinkRequest)
overload. The follow snippet provides an implementation of this method:
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)
Unlike navigation using action or destination IDs, you can navigate to any deep link in your graph, regardless of whether the destination is visible. You can navigate to a destination on the current graph or a destination on a completely different graph.
Actions and MIME types
In addition to Uri
, NavDeepLinkRequest
also supports deep links with actions and MIME types. To add an action to the request, use fromAction()
or setAction()
. To add a MIME type to a request, use fromMimeType()
or setMimeType()
.
For a NavDeepLinkRequest
to properly match an implicit deep link destination, the URI, action, and MIME type must all match the NavDeepLink
in the destination. URIs must match the pattern, the actions must be an exact match, and the MIME types must be related. For example, image/jpg
matches with image/\*
Further contexts
This document covers how to use NavController.navigate()
in the most common use cases. However, the function has a range of overloads that you can use in different contexts, and in tandem with any Ui framework. See the reference documentation for more detail on these overloads.
Further reading
For more information, see the following pages:
- Create a navigation controller
- Navigation and the back stack
- Navigate with options
- Type safety in Kotlin DSL and Navigation Compose