Home » Android navigation component multiple activities

Android navigation component multiple activities

  • by
Android navigation component multiple activities

1. Overview

In this article, we will learn to use the Android navigation component with multiple activities. If you also want a high-level overview of the concepts, refer to the Android Navigation component article.

For using a single activity with multiple fragments, refer Android navigation component example.

2. Android navigation component multiple activities

A navigation component is for apps that use a single activity to swap multiple fragments. The single activity contains a NavHostFragment layout container to display the fragments. We associate it with the navigation graph, which contains the information required for navigation such as fragments (Destinations).

We recommend using a single activity model with multiple fragments. But if you still need to use the navigation component with multiple activities, then you can do it.

  1. Refer section 3 if all your activities contain fragments
  2. Refer section 4 if your destination activity don’t have any fragment.

2.1. Set up project

1. Android navigation component requires Android Studio 3.3 or higher

2. Add Java 8 feature to your project:

android {
    ...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
}
android {
    ...
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

3. Add the required dependencies to your app’s build gradle file.

dependencies {
  def nav_version = "2.3.5"


  implementation "androidx.navigation:navigation-fragment:$nav_version"
  implementation "androidx.navigation:navigation-ui:$nav_version"


  implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
  implementation "androidx.navigation:navigation-ui-ktx:$nav_version"


  implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"


  androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"


  implementation "androidx.navigation:navigation-compose:2.4.0-alpha10"
}
dependencies {
  val nav_version = "2.3.5"


  implementation("androidx.navigation:navigation-fragment:$nav_version")
  implementation("androidx.navigation:navigation-ui:$nav_version")


  implementation("androidx.navigation:navigation-fragment-ktx:$nav_version")
  implementation("androidx.navigation:navigation-ui-ktx:$nav_version")


  implementation("androidx.navigation:navigation-dynamic-features-fragment:$nav_version")


  androidTestImplementation("androidx.navigation:navigation-testing:$nav_version")


  implementation("androidx.navigation:navigation-compose:2.4.0-alpha10")
}

3. Android navigation component multiple activities with fragments

If your activities have fragments, then follow this approach.

It is possible to use the navigation component with multiple activities using the Nested navigation graphs. Thus, you can associate each activity with a navigation graph.

Let’s see a simple example with two activities: MainActivity with fragment MainFragment and DestinationActivity with fragment DestinationFragment.

You should also add your DestinationActivity navigation graph to the MainActivity graph. Then instruct the navigation controller to navigate from Main to Destination activity.

3.1. Add activities and fragments

The activities don’t have any specific code for navigation.

The MainActivity layout contains the NavHostFragment container to show the fragments. The MainFragment has code to instruct the navigation controller to navigate to the DestinationFragment when the user clicks on the "Navigate" button.

MainActivity file
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

    }
}
Main activity xml

The main activity is the container to show the fragments. So, specify the NavHostFragment in the main activity XML file as below:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">

    <androidx.fragment.app.FragmentContainerView
        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/main_nav_graph" />

</androidx.constraintlayout.widget.ConstraintLayout>
MainFragment file
class MainFragment : Fragment() {

    override fun onResume() {
        super.onResume()
        navigate_to_second.setOnClickListener {
            Navigation.findNavController(it).navigate(R.id.action_navigate)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        return inflater.inflate(R.layout.fragment_main, container, false)
    }
}
Main Fragment xml file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".MainFragment">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/main_fragment"
        android:layout_gravity="center"/>

    <Button
        android:id="@+id/navigate_to_second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/navigate_to_second"
        android:layout_gravity="center|bottom"/>

</FrameLayout>
DestinationActivity file
class DestinationActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_destination)
    }
}
DestinationActivity xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/destination_activity"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
DestinationFragment file
class DestinationFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        return inflater.inflate(R.layout.fragment_destination, container, false)
    }
}
DestinationFragment XML
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".DestinationFragment">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:text="@string/destination_fragment" />

</FrameLayout>

3.2. Add navigation graph

main_nav_graph

The MainActivity's navigation graph includes nested navigation graph destination_nav_graph. Also, the MainFragment contains action action_navigate pointing to the DestinationActivity.

So when the user clicks on the "Navigate" button in the MainActivity, then the navigation controller uses this action_navigate and navigates to the DestinationFragment correctly.

<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/main_navigation"
    app:startDestination="@id/mainFragment">

    <include app:graph="@navigation/destination_nav_graph" />
    <fragment
        android:id="@+id/mainFragment"
        android:name="com.tedblob.kotlin.navigationcomponentmultipleactivities.MainFragment"
        android:label="fragment_main"
        tools:layout="@layout/fragment_main">
        <action
            android:id="@+id/action_navigate"
            app:destination="@id/destination_activity" />
    </fragment>
</navigation>
destination_nav_graph

The DestinationActivity is associated with destination_nav_graph and the start destination is DestinationFragment.

<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/destination_activity"
    app:startDestination="@id/destinationFragment">
    <fragment
        android:id="@+id/destinationFragment"
        android:name="com.tedblob.kotlin.navigationcomponentmultipleactivities.DestinationFragment"
        android:label="fragment_destination"
        tools:layout="@layout/fragment_destination" />
</navigation>

4. Android navigation component multiple activities without fragment

Assume you have a MainActivity with fragments. Also, from the MainActivity, you want to navigate to another activity DestinationActivity that doesn’t have any fragments. You can do it by following the below steps:

1. Add your DestinationActivity using <activity> to your navigation graph associated with your MainActivity:

    <activity
        android:id="@+id/destinationActivity"
        android:name="com.tedblob.kotlin.navigationcomponentmultipleactivities.DestinationActivity"
        android:label="DestinationActivity" />

2. Add an action to the fragment element from where you want to navigate to the DestinationActivity. For example, when you click on a button in the MainFragment, it should take you to the DestinationActivity.

<fragment
    android:id="@+id/mainFragment"
    android:name="com.tedblob.kotlin.navigationcomponentmultipleactivities.MainFragment"
    android:label="fragment_main"
    tools:layout="@layout/fragment_main">
    <action
        android:id="@+id/action_navigate3"
        app:destination="@id/destinationActivity" />
</fragment>

3. In your fragment, inform the navigation controller to use the action to navigate to the DestinationActivity.

Navigation.findNavController(it).navigate(R.id.action_navigate3)

You can continue reading for the complete code of this example.

4.1. Add activities and fragments

The activities don’t have any specific code for navigation.

The MainActivity layout contains the NavHostFragment container to show the fragments, and the MainFragment has code to instruct the navigation controller to navigate to the DestinationFragment when the user clicks on the “Navigate” button.

MainActivity file
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

    }
}
Main activity xml

The Main activity is the container to show the fragments. So specify the NavHostFragment in the main activity XML file as below:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">

    <androidx.fragment.app.FragmentContainerView
        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/main_nav_graph" />

</androidx.constraintlayout.widget.ConstraintLayout>
MainFragment file
class MainFragment : Fragment() {

    override fun onResume() {
        super.onResume()
        navigate_to_second.setOnClickListener {
            Navigation.findNavController(it).navigate(R.id.action_navigate3)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        return inflater.inflate(R.layout.fragment_main, container, false)
    }
}
Main Fragment xml file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".MainFragment">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/main_fragment"
        android:layout_gravity="center"/>

    <Button
        android:id="@+id/navigate_to_second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/navigate_to_second"
        android:layout_gravity="center|bottom"/>

</FrameLayout>
DestinationActivity file
class DestinationActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_destination)
    }
}
DestinationActivity xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/destination_activity"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

4.2. Add navigation graph

main_nav_graph

The MainActivity's navigation graph includes activity DestinationActivity. Also, the MainFragment contains action action_navigate pointing to the DestinationActivity.

So when user clicks on the “Navigate” button in the MainActivity, then the navigation controller uses this action_navigate and navigates to the DestinationActivity correctly.

<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/main_navigation"
    app:startDestination="@id/mainFragment">

    <fragment
        android:id="@+id/mainFragment"
        android:name="com.tedblob.kotlin.navigationcomponentmultipleactivities.MainFragment"
        android:label="fragment_main"
        tools:layout="@layout/fragment_main">
        <action
            android:id="@+id/action_navigate3"
            app:destination="@id/destinationActivity" />
    </fragment>
    <activity
        android:id="@+id/destinationActivity"
        android:name="com.tedblob.kotlin.navigationcomponentmultipleactivities.DestinationActivity"
        android:label="DestinationActivity" />
</navigation>

5. Conclusion

To sum up, we have learned to use the Navigation component with multiple activities.

Leave a Reply

Your email address will not be published. Required fields are marked *