That is a part of the Jetpack Compose navigation collection:
I created this straightforward app to check out the navigation part in Jetpack Compose. That is how the app appears to be like like.
These are the steps to implement this straightforward app.
1. Add Navigation Compose Library
In appbuild.gradle
, add this dependency.
dependencies {
implementation "androidx.navigation:navigation-compose:2.5.0-alpha01"
}
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 perform and go that into the NavGraph()
composable perform.
@Composable
personal enjoyable MainScreen() {
SimpleNavComposeAppTheme {
val navController = rememberNavController() NavGraph(navController)
}
}
3. Construct Navigation Graph
The navigation graph appears to be like like this:
Login display is the beginning vacation spot. House display takes no navigation argument. Profile display takes 2 navigation arguments and search display takes 1 navigation argument.
To construct the navigation graph, you utilize NavHost()
composable perform and NavGraphBuilder.composable()
perform to construct every composable display.
enjoyable NavGraph(navController: NavHostController) {
NavHost(
navController = navController,
startDestination = "login"
) {
composable(route = "login") {
}
composable(route = "residence") {
}
...
}
}
To navigate to residence display:
navController.navigate("residence")
To pop again present stack:
navController.popBackStack()
To pop as much as login display:
navController.popBackStack(NavRoute.Login.path, inclusive = false)
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. id
is the primary parameter. showDetails
is the second parameter.
route = "profile/{id}/{showDetails}"
The arguments
parameter appears to be like like this:
arguments = listOf(
navArgument("id") { sort = NavType.IntType },
navArgument("showDetails") { sort = NavType.BoolType }
)
You may specify the NavType
of the parameter. You too can set the defaultValue
to make the argument optionally available.
...
navArgument("showDetails") {
sort = NavType.BoolType
defaultValue = false
}
...
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 optionally available arguement to permit you specify thedefaultValue
.
To retrieve the argument worth, you utilize the NavBackStackEntry.arguments
:
composable( ... ) { navBackStackEntry ->
val args = navBackStackEntry.arguments
val id = args?.getInt("id")!!
showDetails = args?.getBoolean("showDetails")!!
}
That is an instance to navigate to profile display.
val id = 7 val showDetails = true navController.navigate("profile/$id/$showDetails")
Any Route Format Is Fantastic!
As a substitute of utilizing this (which I choose as a result of it’s the easiest kind):
route = "profile/{id}/{showDetails}"
You should use this (required in order for you showDetails
to be optionally available):
route = "profile/{id}/?showDetails={showDetails}"
Or this (required in order for you each id
and showDetails
to be optionally available):
route = "profile/?id={id}/?showDetails={showDetails}"
However please do NOT use this:
route = "profile/{id}{showDetails}"
Please be sure you at the least put a separator (any string) between the navigation parameters. This navigation parameters may very well be parsed wrongly particularly they’re identical knowledge sort.
When you change the route format, it’s good to replace the navigation name too. For instance:
val id = 7 val showDetails = true
navController.navigate("profile/$id/?showDetails=$showDetails")
Too A lot Boilerplate Code
You might have seen, the hard-coded strings are in all places. One mistake can simply crash the app. It’s vulnerable 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 House: NavRoute("residence")
object Profile: NavRoute("profile") {
val id = "id"
val showDetails = "showDetails"
}
object Search: NavRoute("search") {
val question = "question"
}
enjoyable withArgs(vararg args: String): String {
return buildString {
append(path)
args.forEach{ arg ->
append("/$arg")
}
}
}
enjoyable withArgsFormat(vararg args: String) : String {
return buildString {
append(path)
args.forEach{ arg ->
append("/{$arg}")
}
}
}
}
Some utilization examples:
navController.navigate(NavRoute.House.path)
navController.navigate(NavRoute.Search.withArgs(question))
route = NavRoute.Search.withArgsFormat(NavRoute.Search.question)
Closing Ideas
I am unsure my NavRoute strategy above is the nice 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 know the basic first earlier than attempting out this library.
Listed below are the steps to transform this app to make use of this library:
Supply Code
GitHub Repository: Demo_SimpleNavigationCompose