Implement navigation with the Navigation components

Jetpack's Architecture Components make it easy to implement in-app navigation by providing a set of Navigation components that handle most of the details for you.

With Navigation, you create a navigation graph, which is an XML resource that represents the individual destination nodes within your app along with the actions that connect the nodes.

Figure 1 shows a visual representation of a navigation graph for a sample app containing six destinations connected by five actions.

Figure 1. A navigation graph

A destination is any place you can navigate to in your app. While destinations are usually Fragments representing specific screens, Navigation supports other destination types:

  • Activities
  • Navigation graphs and subgraphs - when the destination is a graph or subgraph, you navigate to the start destination of that graph or subgraph
  • Custom destination types

Set up the Navigation for your project

To include Navigation support in your project, add the following to your app's build.gradle file.

dependencies {
    def nav_version = "1.0.0-alpha09"

    implementation "android.arch.navigation:navigation-fragment:$nav_version" // use -ktx for Kotlin
    implementation "android.arch.navigation:navigation-ui:$nav_version" // use -ktx for Kotlin
}

For information on adding other Architecture Components to your project, see Adding components to your project.

Create a navigation graph

To add a navigation graph to your project, do the following:

  1. In the Project window, right-click on the res directory and select New > Android Resource File. The New Resource File dialog appears.
  2. Type a name in the File name field, such as "nav_graph".
  3. Select Navigation from the Resource type drop-down list.
  4. Click OK. The following occurs:
    1. A navigation resource directory is created within the res directory.
    2. A nav_graph.xml file is created within the navigation directory.
    3. The nav_graph.xml file opens in the Navigation Editor. This XML file contains your navigation graph.
  5. Click the Text tab to toggle to the XML text view. You should see an empty navigation graph, as shown in the following example:

    <?xml version="1.0" encoding="utf-8"?>
    <navigation xmlns:android="http://schemas.android.com/apk/res/android">
    </navigation>
    
  6. Click Design to return to the Navigation Editor.

Tour the Navigation Editor

In the Navigation Editor, you can visually edit navigation graphs instead of directly editing the underlying XML.

Figure 2. The Navigation Editor
  1. Destinations: Lists your navigation host and all destinations currently in the Graph Editor.
  2. Graph Editor: Contains a visual representation of your navigation graph.
  3. Attributes: Shows attributes for the currently-selected item in the navigation graph.

Create destinations

The first step in creating a navigation graph is to identify and create the individual destinations for your app. You can create destinations from Fragments and Activities in an existing project, or you can create placeholder destinations that you can later replace with a Fragment or Activity.

If you have an existing Fragment or Activity that you'd like to add to your navigation graph, or if you want to add a placeholder, click New Destination , and then click on the corresponding Fragment, Activity, or placeholder destination in the dropdown that appears. You can now see a preview of the destination in the Design view along with the corresponding XML in the Text view of your navigation graph.

To create a new destination type, do the following:

  1. From the Navigation editor, click New Destination , and then click Create blank destination.

  2. In the New Android Component dialog that appears, enter a Fragment Name. This is the name of the Fragment's class.

  3. To have Android Studio create a corresponding layout resource file for the Fragment, check the box next to Create layout XML, and enter the resource name in the Fragment Layout Name field.

  4. In the Source Language dropdown, choose either Kotlin or Java for the class source file.

  5. Click Finish.

The new destination type appears in the Navigation editor. Android Studio also creates a corresponding class file in the specified source language and, if specified, a layout resource file for the new destination type.

Figure 3 shows an example of a destination and a placeholder.

Figure 3. A destination and a placeholder

You can click on any destination to select it. When selecting a destination, the following attributes appear in the Attributes panel:

  • The Type field indicates whether the destination is implemented as a Fragment or Activity in your source code.
  • The Label field contains the name of the destination’s XML layout file.
  • The ID field contains the ID of the destination which is used to refer to the destination in code.
  • The Class dropdown shows the name of the class that is associated with the destination. You can click this dropdown to change the associated class to another destination type.

Click the Text tab to show the XML view of your navigation graph. The XML contains the same id, name, label, and layout attributes for the destination, as shown below:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    app:startDestination="@id/blankFragment">
    <fragment
        android:id="@+id/blankFragment"
        android:name="com.example.cashdog.cashdog.BlankFragment"
        android:label="Blank"
        tools:layout="@layout/fragment_blank" />
</navigation>

Connect destinations

You must have more than one destination to connect destinations. Following is the XML for a navigation graph with two blank destinations:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    app:startDestination="@id/blankFragment">
    <fragment
        android:id="@+id/blankFragment"
        android:name="com.example.cashdog.cashdog.BlankFragment"
        android:label="fragment_blank"
        tools:layout="@layout/fragment_blank" />
    <fragment
        android:id="@+id/blankFragment2"
        android:name="com.example.cashdog.cashdog.BlankFragment2"
        android:label="Blank2"
        tools:layout="@layout/fragment_blank_fragment2" />
</navigation>

Destinations are connected using actions. To connect two destinations, do the following:

  1. In the Design tab, hover over the right side of the destination that you want users to navigate from. A circle appears on the destination.

    Figure 4. Action connection circle
  2. Click and hold, drag your cursor over the destination you want users to navigate to, and release. A line is drawn to indicate navigation between the two destinations.

    Figure 5. Connected destinations
  3. Click on the arrow to highlight the action. The following attributes appear in the Attributes panel:

    • The Type field contains “Action”.
    • The ID field contains the ID for the action.
    • The Destination field contains the ID for the destination Fragment or Activity.
  4. Click the Text tab to toggle to the XML view. An action element is now added to the source destination. The action has an ID and a destination attribute that contains the ID of the next destination, as shown in the example below:

    <?xml version="1.0" encoding="utf-8"?>
    <navigation xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:android="http://schemas.android.com/apk/res/android"
        app:startDestination="@id/blankFragment">
        <fragment
            android:id="@+id/blankFragment"
            android:name="com.example.cashdog.cashdog.BlankFragment"
            android:label="fragment_blank"
            tools:layout="@layout/fragment_blank" >
            <action
                android:id="@+id/action_blankFragment_to_blankFragment2"
                app:destination="@id/blankFragment2" />
        </fragment>
        <fragment
            android:id="@+id/blankFragment2"
            android:name="com.example.cashdog.cashdog.BlankFragment2"
            android:label="fragment_blank_fragment2"
            tools:layout="@layout/fragment_blank_fragment2" />
    </navigation>
    

Designate a screen as the start destination

The Navigation editor uses a house icon to indicate the first screen users see when opening your app, also known as the start destination.

To choose a different start destination, do the following:

  1. In the Design tab, click on the new start destination to highlight it.

  2. Click the Assign start destination button . Alternatively, you can right-click on the destination and click Set as Start Destination.

Modify an activity to host navigation

An activity hosts navigation for an app in a NavHost. The NavHost is an empty container where destinations are swapped in and out as a user navigates through your app.

The Navigation component’s default NavHost implementation is NavHostFragment.

Add a NavHostFragment using the Layout Editor

You can use the Layout Editor to add a NavHostFragment to an activity by following these steps:

  1. Create a navigation graph resource if you don't already have one.

  2. In your list of project files, double-click on your activity's layout XML file to open it in the Layout Editor.

  3. Within the Palette pane, choose the Containers category, or alternatively search for "NavHostFragment".

  4. Drag the NavHostFragment view onto your activity.

  5. Next, in the Navigation Graphs dialog that appears, choose the corresponding navigation graph to associate with this NavHostFragment, and then click OK.

Back in Text view, notice that Android Studio has added XML similar to the following:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <fragment
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"

        app:defaultNavHost="true"
        app:navGraph="@navigation/mobile_navigation" />

</android.support.constraint.ConstraintLayout>

The app:defaultNavHost="true" attribute ensures that your NavHostFragment intercepts the system Back button. You can also implement this behavior by overwriting AppCompatActivity.onSupportNavigateUp() and calling NavController.navigateUp, as shown in the example below:

Kotlin

override fun onSupportNavigateUp()
        = findNavController(R.id.nav_host_fragment).navigateUp()

Java

@Override
public boolean onSupportNavigateUp() {
    return Navigation.findNavController(this, R.id.nav_host_fragment).navigateUp();
}

Create the NavHostFragment programmatically

You can also use NavHostFragment.create() to programmatically create a NavHostFragment with a specific graph resource, as shown in the example below:

Kotlin

val finalHost = NavHostFragment.create(R.navigation.example_graph)
supportFragmentManager.beginTransaction()
    .replace(R.id.nav_host, finalHost)
    .setPrimaryNavigationFragment(finalHost) // this is the equivalent to app:defaultNavHost="true"
    .commit()

Java

NavHostFragment finalHost = NavHostFragment.create(R.navigation.example_graph);
getSupportFragmentManager().beginTransaction()
    .replace(R.id.nav_host, finalHost)
    .setPrimaryNavigationFragment(finalHost) // this is the equivalent to app:defaultNavHost="true"
    .commit();

Tie destinations to UI widgets

Navigating to a destination is done using the NavController class. A NavController can be retrieved using one of the following static methods:

After you retrieve a NavController, use its navigate() method to navigate to a destination. The navigate() method accepts a resource ID. The ID can be the ID of a specific destination in the navigation graph or of an action. Using the ID of the action, instead of the resource ID of the destination, has advantages, such as associating transitions with your navigation. For more on transitions, refer to Create a transition between destinations.

The following code snippet shows how 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);
    }
});

The Android system maintains a back stack containing the last visited destination. The first destination of your app is placed on the stack when the user opens the app. Each call to the navigate() method puts another destination on the top of the stack. Conversely, pressing the Up or Back button calls the NavController.navigateUp() and NavController.popBackStack() methods, respectively, to pop the top destination off of the stack.

For buttons, you can also use the Navigation class’s createNavigateOnClickListener() convenience method to navigate to a destination:

Kotlin

button.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.next_fragment, null))

Java

button.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.next_fragment, null));

To handle other common UI components, such as the top app bar and bottom navigation, see Update UI components with NavigationUI.

In Android, a deep link is a URI that points to a specific destination in an app. These URIs are useful when you want to send users to a specific destination to perform some task in your app, such as a send money flow allowing the user to quickly send money to someone.

To assign a deep link to a destination in your navigation graph:

  1. In the Design view, select the destination for the deep link.

  2. Click the Add deep link button (or click + in the Deep Links section of the Attributes panel). An Add Deep Link dialog appears.

  3. Type a URI into the URI field, such as "www.cashdog.com/sendmoney" which represents the start destination of a send money nested graph in an app.

    Note the following:

    • URIs without a scheme are assumed as http and https. For example, www.cashdog.com matches http://www.cashdog.com and https://www.cashdog.com.
    • Placeholders in the form of {placeholder_name} matches 1 or more characters. The String value of the placeholder is available in the arguments Bundle with a key of the same name. For example, http://www.example.com/users/{id} matches http://www.example.com/users/4.
    • The .* wildcard can be used to match 0 or more characters.
  4. (optional) Check Auto Verify to require Google to verify that you are the owner of the URI. For more information, see Verify Android App Links.

  5. Click Add. A link icon appears above the selected destination to indicate that destination has a deep link.

  6. Click the Text tab to toggle to the XML view. A nested deep link element has been added to the destination:

    <deepLink app:uri="https://cashdog.com/sendmoney"/>
    

When a user presses the Back button from a deep link destination, they navigate back up the navigation stack just as though they entered your app from the app's entry point.

Add an intent filter for a deep link

You must make additions to your manifest.xml file to enable deep linking in your app:

  • For Android Studio 3.0 and 3.1, you must manually add an intent-filter element. For more information, see Create Deep Links to App Content.
  • For Android Studio 3.2+, you can add a nav-graph element to your activity elements:

    <activity name=".MainActivity">
       <nav-graph android:value="@navigation/main_nav" />
    </activity>
    

    As part of the manifest merging build step, this element is replaced with the generated <intent-filter> elements needed to match all of the deep links in the navigation graph.

You can use the NavDeepLinkBuilder class to construct a PendingIntent that takes the user to a specific destination.

When this deep link is triggered, the task back stack is cleared and replaced with the deep link destination. When nesting graphs, the start destination from each level of nesting—that is, the start destination from each <navigation> element in the hierarchy—is also added to the stack.

You can construct a PendingIntent directly with NavDeepLinkBuilder(Context), as shown in the example below. Note that if the provided context is not an Activity, the constructor uses PackageManager.getLaunchIntentForPackage() as the default activity to launch, if available.

Kotlin

val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.mobile_navigation)
    .setDestination(R.id.android)
    .setArguments(args)
    .createPendingIntent()

Java

PendingIntent pendingIntent = new NavDeepLinkBuilder(context)
    .setGraph(R.navigation.mobile_navigation)
    .setDestination(R.id.android)
    .setArguments(args)
    .createPendingIntent();

For a complete navigation project that includes this example, see the Navigation Codelab.

Create a transition between destinations

The Navigation Components provide functionality to easily add transitions, such as fade-in and fade-out, between destinations. To add a transition, do the following:

  1. Create your animation resource files. Navigation supports property and view animations. For further information, see Animation resources.
  2. In the Design tab of the Navigation Editor, click on the action where the transition should occur.
  3. In the Transitions section of the Attributes panel, click the down arrow next to Enter to show the list of available transitions in your project.
  4. Select the transition to occur when a user enters the destination.
  5. Back in the Transitions section, click the down arrow next to Exit, and then choose a transition to occur when a user exits the destination.
  6. Click the Text tab to toggle to the XML text view. The XML for the transition appears in the <action> element for the specified action. The action is embedded within the XML for the destination that is active before the transition occurs. In the following example, specifyAmountFragment is the active destination, so it contains the action with the transition animations:

    <fragment
        android:id="@+id/specifyAmountFragment"
        android:name="com.example.buybuddy.buybuddy.SpecifyAmountFragment"
        android:label="fragment_specify_amount"
        tools:layout="@layout/fragment_specify_amount">
        <action
            android:id="@+id/confirmationAction"
            app:destination="@id/confirmationFragment"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"
            app:popEnterAnim="@anim/slide_in_left"
            app:popExitAnim="@anim/slide_out_right" />
     </fragment>
    

    In this example we have transitions that take place when moving to a destination (enterAnim and exitAnim and when exiting that destination (popEnterAnim and popExitAnim).

Add Shared Element Transitions between destinations

In addition to transition animations, Navigation supports adding shared element transitions between destinations.

Shared element transitions, unlike animations, are supplied programmatically rather than through your navigation XML file, as they require referencing the View instances that you wish to include in the shared element transition.

Each type of destination implements this programmatic API through a subclass of the Navigator.Extras interface. The Extras are passed to a call to navigate().

Fragment Destination Shared Element Transitions

The FragmentNavigator.Extras class allows you to attach shared elements to navigate() calls to Fragment destinations, as shown in the example below:

Kotlin

val extras = FragmentNavigatorExtras(
    imageView to "header_image",
    titleView to "header_title")
view.findNavController().navigate(R.id.confirmationAction,
    null, // Bundle of args
    null, // NavOptions
    extras)

Java

FragmentNavigator.Extras extras = new FragmentNavigator.Extras.Builder()
    .addSharedElement(imageView, "header_image")
    .addSharedElement(titleView, "header_title")
    .build();
Navigation.findNavController(view).navigate(R.id.details,
    null, // Bundle of args
    null, // NavOptions
    extras);

Activity Destination Shared Element Transitions

Activities rely on ActivityOptionsCompat to control Shared Element Transitions as detailed in the Start an activity with a shared element documentation and as shown in the example below:

Kotlin

// Rename the Pair class from the Android framework to avoid a name clash
import android.util.Pair as UtilPair
...
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
        UtilPair.create(imageView, "header_image"),
        UtilPair.create(titleView, "header_title"))
val extras = ActivityNavigator.Extras(options)
view.findNavController().navigate(R.id.details,
    null, // Bundle of args
    null, // NavOptions
    extras)

Java

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
        Pair.create(imageView, "header_image"),
        Pair.create(titleView, "header_title"));

ActivityNavigator.Extras extras = new ActivityNavigator.Extras.Builder()
    .setActivityOptions(options)
    .build();
Navigation.findNavController(view).navigate(R.id.details,
    null, // Bundle of args
    null, // NavOptions
    extras);

Report an issue

If you encounter any issues with the Navigation Editor, please submit a report in Issue Tracker. For information on how to provide the most helpful information in issue reports, see Report a bug.

What's next

For more information about Navigation, see the following topics: