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 in the navigation graph, use
NavController.navigate(route)
. With this overload,
navigate()
takes a
single
String
argument. This is the
route
. It serves as the key to a
destination.
navController.navigate("friendslist")
To navigate using a
route
string, you first need to create your
NavGraph
such that each destination is associated with a
route
. For composables, you do
so with the
composable()
function.
For more information, see
Navigate to a destination
.
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 a clear example of this.
Example
As a demonstration of the preceding section, observe these points in the
following snippet:
- The
MyAppNavHost
composable holds the
NavController
instance.
- Accordingly, calls to
navigate()
should occur there and not in a lower
composable like
ProfileScreen
.
ProfileScreen
contains a button that navigates the user to
FriendsList
when clicked. However, it does not call
navigate()
itself.
- Instead, the button calls a function that is exposed as the parameter
onNavigateToFriends
.
- When
MyAppNavHost
adds
ProfileScreen
to the navigation graph, for
onNavigateToFriends
it passes a lambda that calls
navigate()
.
- This ensures that when the user presses the button
ProfileScreen
, they
navigate correctly to
friendsList
.
@Composable
fun MyAppNavHost(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController(),
startDestination: String = "profile"
) {
NavHost(
modifier = modifier,
navController = navController,
startDestination = startDestination
) {
composable("profile") {
ProfileScreen(
onNavigateToFriends = { navController.navigate("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: