Skip to main content

Jetpack Compose: Navigation

·4 mins

A Practical Introduction #

In this tutorial, you’ll learn the basics of Jetpack Compose Navigation, which is a set of related classes that help you create clearly structured and easy-to-understand code for navigation in your Android app. By using these classes, you’ll be able to simplify the navigation code and make it more organized, which will make it easier to maintain and update. Let’s get started!

This is what we will build:

The animation below shows a finished example application where the user can navigate between several different views. To achieve this, the tutorial will guide you through the use of the NavHost, NavController, and Navigation composable functions.

navigation.gif

Dependencies #

To use Jetpack Compose Navigation, you need to add the following dependency to your build.gradle:

dependencies {
  ...
  implementation 'androidx.navigation:navigation-compose:2.5.3'
}

The Code #

The code below shows the full example of the Jetpack Compose Navigation animation above. We’ll go through it step-by-step in the following paragraphs.

@Composable
fun NavigationView() {
  val navController = rememberNavController()
  NavHost(navController = navController, startDestination = "home") {
    composable("home") {
      HomeScreen(navController)
    }
    composable("settings") {
      SettingsScreen(
        onHome = { navController.popBackStack() },
        onProfile = { navController.navigate("profile") }
      )
    }
    composable("profile") {
      ProfileScreen { navController.popBackStack("home", false) }
    }
  }
}

@Composable
fun HomeScreen(navController: NavHostController) {
  Column(
    Modifier.fillMaxSize(),
      horizontalAlignment = Alignment.CenterHorizontally,
      verticalArrangement = Arrangement.Center
  ) {
    Text("Home Screen")
    Button(onClick = { navController.navigate("settings") }) {
      Text("Go to Settings")
    }
    Button(onClick = { navController.navigate("about") }) {
      Text("Go to About")
    }
  }
}

@Composable
fun SettingsScreen(onHome: () -> Unit, onProfile: () -> Unit) {
  Column(
    Modifier.fillMaxSize(),
    horizontalAlignment = Alignment.CenterHorizontally,
    verticalArrangement = Arrangement.Center
  ) {
    Text("Settings Screen")
    Button(onClick = onHome) { Text("Go back to Home") }
    Button(onClick = onProfile) { Text("Go to Profile") }
  }
}

@Composable
fun ProfileScreen(onHome: () -> Unit) {
  Column(
    Modifier.fillMaxSize(),
    horizontalAlignment = Alignment.CenterHorizontally,
    verticalArrangement = Arrangement.Center
  ) {
    Button(onClick = onHome) {
      Text("Go back to Home")
    }
  }
}

The full Android Studio project can be found in my Github-repository of Android and iOS code examples.

A basic example of Jetpack Compose Navigation includes the following components: NavHost, **NavController,**and Navigation composable. The NavHost is the container that holds all of the navigation destinations within the app. The NavController is responsible for managing the navigation between different destinations and the Navigation composable is used to declare a specific destination within the NavHost.

The navigation stack refers to the order of composables that the user has navigated through, with the current composable being the top of the stack. navigate, popUpTo, and popBack are all functions used to manage the navigation stack. The class responsible for the navigation stack is the NavHost composable.

navigate is used to navigate from one composable to another composable, such as from HomeScreen to SettingsScreen in this example. The navigate function takes two arguments, the first being the destination composable name as a string, and the second being an optional argument for passing data to the destination composable.

popUpTo is used to navigate back to a specific composable in the navigation stack. It takes the destination composable name as an argument and discards all composables that were added after it. In this example, popUpTo("home") navigates back to the HomeScreen composable while discarding the SettingsScreen and ProfileScreen composables.

popBack is used to navigate back one step in the navigation stack. It discards the current composable and takes the user back to the previous composable in the stack. In this example, popBack() takes the user back to the SettingsScreen composable from the AboutScreen composable.

In the provided code, there are two areas that could be improved.

Firstly, passing the navController into a view is considered an anti-pattern and should be avoided. Views should not be aware of any navigation aspects, but should only inform the parent about a certain event that might require navigation. This way, the parent can handle the navigation logic without involving the view.

Secondly, using Strings directly for the navigation routes presents a potential problem. A simple typo can cause your code to crash, making debugging difficult. Instead, it is recommended to use enums or sealed classes to represent navigation routes. This approach provides compile-time safety, ensuring that typos and incorrect navigation routes are caught before runtime.

By implementing these best practices, your code will be easier to maintain, more organized, and less prone to errors.

That wraps up this brief introduction to the topic. I trust you found it both helpful and informative. Please don’t hesitate to leave a comment if you have any questions or suggestions.

Thank you for reading!

https://twissmueller.medium.com/membership

Resources #