Simple Jetpack Compose Navigation Example

Easy app to indicate completely different screens in Jetpack Compose and navigate between them.

This text was initially printed at vtsen.hashnode.dev on April 23, 2022.

I created this easy app to check out the navigation component in Jetpack Compose. That is how the app appears like.

These are the steps to implement this easy app.



1. Add Navigation Compose Library

In appbuild.gradle, add this dependency.

dependencies {
    implementation "androidx.navigation:navigation-compose:2.5.0-alpha01"
}
Enter fullscreen mode

Exit fullscreen mode



2. Create NavHostController

NavHostController is required to construct the navigation graph within the subsequent step which is used to navigate to completely different screens.

Create this NavHostController utilizing rememberNavController() in your root composable operate and move that into the BuildNavGraph() composable operate.

@Composable
personal enjoyable MainScreen() {
    SimpleNavComposeAppTheme {
        val navController = rememberNavController()
        BuildNavGraph(navController)
    }
}
Enter fullscreen mode

Exit fullscreen mode



3. Construct Navigation Graph

The navigation graph appears like this:

  • Login Display -> Dwelling Display -> Profile Display
  • Login Display -> Dwelling Display -> Search Display

Login display screen is the beginning vacation spot. Dwelling display screen takes no navigation argument. Profile display screen takes 2 navigation arguments and search display screen takes 1 navigation argument.

To construct the navigation graph, you employ NavHost() composable operate and NavGraphBuilder.composable() operate to construct every composable display screen.

enjoyable BuildNavGraph(navController: NavHostController) {
    NavHost(
        navController = navController,
        startDestination = "login"
    ) {
        composable(route = "login") {
            //name LoginScreen composable operate right here
        }

        composable(route = "residence") {
            //name HomeScreen composable operate right here
        }
        ...
    }
}

Enter fullscreen mode

Exit fullscreen mode

To navigate to residence display screen:

navController.navigate("residence")
Enter fullscreen mode

Exit fullscreen mode

To pop again present stack:

navController.popBackStack()
Enter fullscreen mode

Exit fullscreen mode

To pop as much as login display screen:

navController.popBackStack(NavRoute.Login.path, inclusive = false)
Enter fullscreen mode

Exit fullscreen mode



Navigation With Arguments

navGraphBuilder.composable has 2 parameters – route and arguments. To navigation with argument, we need to replace each route and arguments parameters.

That is route format for profile display screen. id is the primary parameter. showDetails is the second parameter.

route = "profile/{id}/{showDetails}"
Enter fullscreen mode

Exit fullscreen mode

The arguments parameter appears like this:

arguments = listOf(
    navArgument("id") {
        sort = NavType.IntType
    }
    ,
    navArgument("showDetails") {
        sort = NavType.BoolType
    }
)
Enter fullscreen mode

Exit fullscreen mode

You’ll be able to specify the NavType of the parameter. You can too set the defaultValue to make the argument elective.

...
    navArgument("showDetails") {
        sort = NavType.BoolType
        defaultValue = false
    }
...
Enter fullscreen mode

Exit fullscreen mode

I personally will keep away from utilizing defautValue as a result of it requires your path to comply with sure format (i.e. "profile/{id}/?showDetails={showDetails}"). ?showDetails is the elective arguement to permit you specify the defaultValue.

To retrieve the argument worth, you employ the NavBackStackEntry.arguments:

composable(
   ...
) { navBackStackEntry ->

    val args = navBackStackEntry.arguments

    // get id param worth
    val id = args?.getInt("id")!!
    // get showDetails param worth
    val showDetails = args?.getBoolean("showDetails")!!

    // name profile display screen composable operate right here
    ...
}
Enter fullscreen mode

Exit fullscreen mode

That is an instance to navigate to profile display screen.

val id = 7
val showDetails = true
navController.navigate("profile/$id/$showDetails")
Enter fullscreen mode

Exit fullscreen mode



Any Route Format Is Effective!

As a substitute of utilizing this (which I desire as a result of it’s the easiest type):

route = "profile/{id}/{showDetails}"
Enter fullscreen mode

Exit fullscreen mode

You should utilize this (required if you would like showDetails to be elective):

route = "profile/{id}/?showDetails={showDetails}"
Enter fullscreen mode

Exit fullscreen mode

Or this (required if you would like each id and showDetails to be elective): :

route = "profile/?id={id}/?showDetails={showDetails}"
Enter fullscreen mode

Exit fullscreen mode

However please do NOT use this:

route = "profile/{id}{showDetails}"
Enter fullscreen mode

Exit fullscreen mode

Please be sure to at the least put a separator (any string) between the navigation parameters. This navigation parameters might be parsed wrongly particularly they’re similar knowledge sort.

When you change the route format, it is advisable replace the navigation name too. For instance:

val id = 7 
val showDetails = true
navController.navigate("profile/$id/?showDetails=$showDetails")
Enter fullscreen mode

Exit fullscreen mode



Too A lot Boilerplate Code

You will have seen, the hard-coded strings are in every single place. One mistake can simply crash the app. It’s susceptible to errors.

So what I did is to create this NavRoute class that has all of the hard-coded strings there. I additionally embody a utility capabilities (i.e. withArgs() to construct the navigation path and withArgsFormat() to construct the route format string.

sealed class NavRoute(val path: String) {

    object Login: NavRoute("login")

    object Dwelling: NavRoute("residence")

    object Profile: NavRoute("profile") {
        val id = "id"
        val showDetails = "showDetails"
    }

    object Search: NavRoute("search") {
        val question = "question"
    }

    // construct navigation path (for display screen navigation)
    enjoyable withArgs(vararg args: String): String {
        return buildString {
            append(path)
            args.forEach{ arg ->
                append("/$arg")
            }
        }
    }

    // construct and setup route format (in navigation graph)
    enjoyable withArgsFormat(vararg args: String) : String {
        return buildString {
            append(path)
            args.forEach{ arg ->
                append("/{$arg}")
            }
        }
    }
}
Enter fullscreen mode

Exit fullscreen mode

Some utilization examples:

// navigate to residence
navController.navigate(NavRoute.Dwelling.path)

// navigate to look
navController.navigate(NavRoute.Search.withArgs(question))

// setup route for search display screen with question param
route = NavRoute.Search.withArgsFormat(NavRoute.Search.question)
Enter fullscreen mode

Exit fullscreen mode



Closing Ideas

I am unsure my NavRoute approach above is the great one. I am additionally unsure if it makes the code unreadable? Possibly a bit? Nevertheless, it at the least can do away with many hard-coded strings and no extra boilerplate code.

There’s a Compose Locations library which removes much more boilerplate code. I feel it’s higher to grasp the basic first earlier than making an attempt out this library.

Listed below are the steps to transform this app to make use of this library:



Supply Code

GitHub Repository: Demo_SimpleNavigationCompose



See Additionally

Add a Comment

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