Skip to main content

Using Navigation Component

1. Setting Up Navigation Graph

Navigation graphs define the navigation structure of your app using XML files. They consist of destinations, actions, and navigation parameters.

Element Description Usage
navigation Root element for the navigation graph <navigation>
fragment Represents a destination in the navigation graph <fragment>
action Defines navigation between destinations <action>

Example: Basic Navigation Graph Setup

<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/homeFragment">

    <fragment
        android:id="@+id/homeFragment"
        android:name="com.example.HomeFragment"
        android:label="Home" />

    <fragment
        android:id="@+id/profileFragment"
        android:name="com.example.ProfileFragment"
        android:label="Profile" />

    <action
        android:id="@+id/action_home_to_profile"
        app:destination="@id/profileFragment" />

</navigation>
Note: The startDestination attribute specifies the initial destination when the navigation graph is loaded.

2. Configuring NavHost Fragment

Property Values Description
android:name androidx.navigation.fragment.NavHostFragment The class name for the NavHost Fragment
app:navGraph @navigation/nav_graph Reference to the navigation graph resource file
app:defaultNavHost true Enables the fragment to receive system back button events

Example: NavHost Fragment in XML

<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:navGraph="@navigation/nav_graph"
    app:defaultNavHost="true" />

3. Navigating Between Destinations

Destination Navigation Action Description
HomeFragment navController.navigate(R.id.action_home_to_detail) Navigates from HomeFragment to DetailFragment
ProfileFragment navController.navigate(R.id.action_profile_to_settings) Opens SettingsFragment from ProfileFragment

Example: Navigation in Kotlin

class HomeFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_home, container, false)
        val button = view.findViewById<Button>(R.id.button)
        button.setOnClickListener {
            findNavController().navigate(R.id.action_home_to_detail)
        }
        return view
    }
}
Note: Navigation actions are defined in nav_graph.xml and must be unique.
Warning: Avoid hardcoding navigation paths; use named actions for maintainability.

4. Passing Arguments

Argument Type Description Usage Notes
String Passes a string value navArgs.putString("name", "John") Can be null
Int Passes an integer value navArgs.putInt("age", 25) Supports all integer types
Boolean Passes a boolean value navArgs.putBoolean("isActive", true) Can be null
Serializable Passes a serializable object navArgs.putSerializable("user", userObject) Object must implement Serializable
Parcelable Passes a parcelable object navArgs.putParcelable("user", userObject) Object must implement Parcelable

Example: Passing Arguments in Navigation

class UserFragment : Fragment() {
    private val args: UserFragmentArgs by navArgs()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_user, container, false)
        val userName = args.userName
        val userAge = args.userAge

        // Use the arguments here
        return view
    }
}

Example: Passing Arguments in Navigation Graph

<fragment
    android:id="@+id/userFragment"
    android:name="com.example.UserFragment"
    tools:layout="@layout/fragment_user" >
    <argument
        android:name="userName"
        app:argType="string" />
    <argument
        android:name="userAge"
        app:argType="integer" />
</fragment>
Note: Arguments must be defined in the navigation graph before they can be used in a fragment.

5. Using Navigation Actions

Action Description Parameters Example
navigate() Navigates to a destination navController, actionId navController.navigate(R.id.action_to_destination)
popBackStack() Removes the top destination from the back stack navController, inclusive navController.popBackStack(true)
navigateUp() Navigates up to the parent destination navController navController.navigateUp()

Example: Using Navigation Actions in a Fragment

class HomeFragment : Fragment() {
    private lateinit var navController: NavController

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_home, container, false)
        navController = findNavController()
        
        view.findViewById<Button>(R.id.button).setOnClickListener {
            navController.navigate(R.id.action_home_to_details)
        }
        
        return view
    }
}
Note: Navigation actions are defined in the nav_graph.xml file and must be unique within a navigation graph.
Warning: Avoid using navigateUp() in fragments that are not part of a navigation graph.
Property Description Example
deepLink Defines a deep link URI pattern for navigation deepLink { uri = "https://example.com/product/{id}" }
uri URI pattern for deep link matching uri = "app://myapp/product/{id}"
<deepLink
    uri="https://myapp.com/product/{id}" />
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val navController = findNavController(R.id.nav_host_fragment)
        val navGraph = navController.navInflater.inflate(R.navigation.nav_graph)

        // Handle deep link
        if (intent.data != null) {
            val navOptions = NavOptions.Builder()
                .setLaunchSingleTop(true)
                .build()

            navController.navigate(
                R.id.productFragment,
                Bundle().apply { putString("id", intent.data?.lastPathSegment) },
                navOptions
            )
        }
    }
}
Note: Deep links must be defined in the navigation graph and handled in the activity or fragment that receives them.

7. Implementing Conditional Navigation

Condition Description Implementation
Navigation Graph Defines navigation flow and destinations
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/nav_graph"
    app:startDestination="@id/homeFragment">
    <fragment
        android:id="@+id/homeFragment"
        android:name="com.example.HomeFragment" />
    <fragment
        android:id="@+id/detailFragment"
        android:name="com.example.DetailFragment" />
</navigation>
Safe Args Plugin Generates type-safe arguments for navigation
implementation "androidx.navigation:navigation-fragment-ktx:2.7.5"
implementation "androidx.navigation:navigation-ui-ktx:2.7.5"
Conditional Navigation Navigation based on runtime conditions
val navController = findNavController()
val currentDestination = navController.currentDestination?.id

if (currentDestination == R.id.homeFragment) {
    navController.navigate(R.id.detailFragment)
}

Example: Conditional Navigation in Fragment

class HomeFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_home, container, false)
        
        val navController = findNavController()
        view.findViewById<Button>(R.id.button).setOnClickListener {
            val userLoggedIn = getUserStatus()
            if (userLoggedIn) {
                navController.navigate(R.id.action_home_to_profile)
            } else {
                navController.navigate(R.id.action_home_to_login)
            }
        }
        
        return view
    }
}
Note: Use findNavController() to access the NavController from any Fragment.
Warning: Avoid hardcoding navigation logic in UI components; prefer centralized navigation handling.

8. Using Bottom Navigation with NavController

Property Description Values
navController Instance of NavController used to navigate between destinations NavController
bottomNavigationView Reference to the BottomNavigationView component BottomNavigationView

Example: Setting up Bottom Navigation with NavController

class MainActivity : AppCompatActivity() {
    private lateinit var navController: NavController

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

        val navView: BottomNavigationView = findViewById(R.id.nav_view)
        val navHostFragment = supportFragmentManager
            .findFragmentById(R.id.nav_host_fragment) as NavHostFragment
        navController = navHostFragment.navController

        navView.setupWithNavController(navController)
    }
}
Note: The setupWithNavController method automatically maps the navigation graph to the bottom navigation items.

Key Points

  • NavController manages navigation between destinations.
  • BottomNavigationView provides a UI for bottom navigation.
  • Use setupWithNavController to bind them together.

9. Managing Navigation Backstack

Example: Clearing the Back Stack

val navController = findNavController()
navController.navigate(R.id.action_to_destination) {
    popUpTo(R.id.nav_graph_start) {
        inclusive = true
    }
}
Property Description Values
popUpTo Destination ID to pop up to R.id.destination_id
inclusive Whether to include the destination in the pop true or false
Note: Use popUpTo with inclusive = true to clear the back stack up to and including a specific destination.

Example: Adding to Back Stack

val navController = findNavController()
navController.navigate(R.id.action_to_destination) {
    // Default behavior adds to back stack
}

Workflow: Managing Back Stack

  1. Identify the destination to navigate to
  2. Determine if you want to clear or preserve the back stack
  3. Use popUpTo with appropriate flags to manage the stack
  4. Ensure proper handling of navigation in UI components

10. Navigating with Animations

Animation Type Description Usage
slide Slide animation from left to right or vice versa navOptions { anim { enter = R.anim.slide_in_right; exit = R.anim.slide_out_left } }
fade Fade in/out animation navOptions { anim { enter = R.anim.fade_in; exit = R.anim.fade_out } }
popUpTo Pop back to a specific destination navOptions { popUpTo(R.id.homeFragment) }

Example: Slide Animation

val navOptions = NavOptions.Builder()
    .setEnterAnim(R.anim.slide_in_right)
    .setExitAnim(R.anim.slide_out_left)
    .build()

navController.navigate(R.id.destination, null, navOptions)

Example: Fade Animation

val navOptions = NavOptions.Builder()
    .setEnterAnim(R.anim.fade_in)
    .setExitAnim(R.anim.fade_out)
    .build()

navController.navigate(R.id.destination, null, navOptions)

11. Using Navigation Compose

Example: Basic Navigation Compose Setup

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController

@Composable
fun NavigationExample() {
    val navController = rememberNavController()
    NavHost(
        navController = navController,
        startDestination = "home"
    ) {
        composable("home") {
            HomeScreen(navController)
        }
        composable("details") {
            DetailsScreen()
        }
    }
}

@Composable
fun HomeScreen(navController: NavHostController) {
    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        // Home content
    }
}

@Composable
fun DetailsScreen() {
    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        // Details content
    }
}
Feature Description Notes
NavHost NavHost is the container for navigation graph Must be used inside a Composable
composable Defines a screen in the navigation graph Used to define each screen in the app
startDestination Initial screen to display Must be a valid route name
Note: Navigation Compose is part of Jetpack Compose and requires androidx.navigation:navigation-compose dependency.

Example: Passing Data Between Screens

import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.navArgument
import androidx.navigation.compose.rememberNavController

@Composable
fun DataPassingExample() {
    val navController = rememberNavController()
    NavHost(
        navController = navController,
        startDestination = "home"
    ) {
        composable(
            "home",
            arguments = listOf(
                navArgument("userId") {
                    type = NavType.IntType
                }
            )
        ) { backStackEntry ->
            val userId = backStackEntry.arguments?.getInt("userId") ?: 0
            HomeScreenWithId(userId, navController)
        }
        composable("details/{userId}") { backStackEntry ->
            val userId = backStackEntry.arguments?.getString("userId") ?: ""
            DetailsScreenWithId(userId)
        }
    }
}
import androidx.navigation.NavDeepLinkRequest
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable

@Composable
fun DeepLinkExample() {
    val navController = rememberNavController()
    NavHost(
        navController = navController,
        startDestination = "home"
    ) {
        composable(
            "home",
            deepLinks = listOf(
                NavDeepLinkRequest.Builder
                    .fromUri("android-app://com.example.app/home")
                    .build()
            )
        ) {
            HomeScreen(navController)
        }
    }
}

Was this article helpful?