Advertisement

Responsive Advertisement

NavController or NavFragment or Navhost in Jetpack compose with popbackstack , navargs

  •  Step 1 :-

    Add dependency first if you're using java for kotlin use val instead of def.

def nav_version = "2.8.1"

implementation("androidx.navigation:navigation-compose:$nav_version")
  • Step 2:-

    Make Sealed class of Screens with parameters of route 

    sealed class Screens(val route: String) {

    data object HomeScreen : Screens("Home")
    data object ProfileScreen : Screens("Profile")
    data object DetailScreen : Screens("Details")

    }


  • Step 3 :-

    Setup Navhost and route like navgraph in navfragment

    @Composable
    fun setUpnavGraph(
    navHostController: NavHostController
    ) {
    NavHost(navController = navHostController, startDestination = Screens.HomeScreen.route) {
    composable(route = Screens.HomeScreen.route){
    HomeScreen(navController = navHostController)
    }
    composable(route = Screens.DetailScreen.route){
    DetailScreen(navController = navHostController)
    }
    composable(route = Screens.ProfileScreen.route){
    ProfileScreen(navController = navHostController)
    }
    }
    }

    Here i have already created composable screens like Home,Profile,Details.


  • Step 4 :-

    In Component Activity you have to initialize 


    private lateinit var navcontroller:NavHostController
    and then on create

    navcontroller= rememberNavController()
    setUpnavGraph(navcontroller)

  • Step 5 :-
    @Composable
    fun HomeScreen(
    navController: NavController
    ) {

    Box(
    modifier = Modifier
    .fillMaxSize()
    .background(MaterialTheme.colorScheme.primary),
    contentAlignment = Alignment.Center,
    ) {
    Text(
    modifier = Modifier.clickable {
    navController.navigate(Screens.ProfileScreen.route)
    },
    text = "Home",
    textAlign = TextAlign.Center,
    fontSize = MaterialTheme.typography.headlineLarge.fontSize,
    fontWeight = FontWeight.Normal,
    color = Color.Black,

    )

    }

    }


    @Preview(showBackground = true)
    @Composable
    fun Preview() {
    HomeScreen(navController = rememberNavController())
    }
    This is my  Home Screen

    @Composable
    fun ProfileScreen(
    navController: NavController
    ) {

    Box(
    modifier = Modifier
    .fillMaxSize()

    .background(MaterialTheme.colorScheme.inversePrimary),
    contentAlignment = Alignment.Center,
    ) {
    Text(
    text = "Profile",
    modifier = Modifier.clickable {
    // navController.navigate(Screens.DetailScreen.route)


    //for back button icon click you can use
    /*navController.popBackStack()*/


    navController.navigate(Screens.DetailScreen.route)


    },
    textAlign = TextAlign.Center,
    fontSize = MaterialTheme.typography.headlineLarge.fontSize,
    fontWeight = FontWeight.Normal,
    color = Color.Black,

    )

    }

    }
    This is my Profile Screen

    @Composable
    fun DetailScreen(
    navController: NavController
    ) {

    Box(
    modifier = Modifier
    .fillMaxSize()

    .background(MaterialTheme.colorScheme.onSurface)
    ,
    contentAlignment = Alignment.Center,
    ) {
    Text(
    modifier = Modifier.clickable {
    navController.navigate(Screens.HomeScreen.route){
    popUpTo(Screens.HomeScreen.route){
    inclusive=true
    }

    }
    },
    text = "Details",
    textAlign = TextAlign.Center,
    fontSize = MaterialTheme.typography.headlineLarge.fontSize,
    fontWeight = FontWeight.Normal,
    color = Color.Black,

    )

    }

    }
    This is My Detail Screen


  • Screenshots :-





  • If You want to pass arguement in screens 

    sealed class Screens(val route: String) {

    data object HomeScreen : Screens("Home")
    data object ProfileScreen : Screens("Profile/{id}")
    data object DetailScreen : Screens("Details")

    }
    @Composable
    fun setUpnavGraph(
    navHostController: NavHostController
    ) {
    NavHost(navController = navHostController, startDestination = Screens.HomeScreen.route) {
    composable(route = Screens.HomeScreen.route) {
    HomeScreen(navController = navHostController)
    }
    composable(route = Screens.DetailScreen.route) {
    DetailScreen(navController = navHostController)
    }
    composable(route = Screens.ProfileScreen.route,
    arguments = listOf(navArgument(name = "id") {
    type = NavType.IntType
    })
    ) {
    Log.e("roshan",it.arguments?.getInt("id").toString())
    ProfileScreen(navController = navHostController)
    }
    }
    }

    @Composable
    fun HomeScreen(
    navController: NavController
    ) {

    Box(
    modifier = Modifier
    .fillMaxSize()
    .background(MaterialTheme.colorScheme.primary),
    contentAlignment = Alignment.Center,
    ) {
    Text(
    modifier = Modifier.clickable {
    navController.navigate("Profile/"+1)
    },
    text = "Home",
    textAlign = TextAlign.Center,
    fontSize = MaterialTheme.typography.headlineLarge.fontSize,
    fontWeight = FontWeight.Normal,
    color = Color.Black,

    )

    }

    }


    @Preview(showBackground = true)
    @Composable
    fun Preview() {
    HomeScreen(navController = rememberNavController())
    }
    Note :-   You can also take const varaible name and pass same for this


    You can use function for pass arguements.

    const val ARGUEMENT1="id"
    sealed class Screens(val route: String) {

    data object HomeScreen : Screens("Home")
    data object ProfileScreen : Screens("Profile/{$ARGUEMENT1}")
    fun passId(id:Int):String{
    return "Profile/$id"
    }
    data object DetailScreen : Screens("Details")

    }
    modifier = Modifier.clickable {
    navController.navigate(Screens.ProfileScreen.passId(2))
    },
    composable(route = Screens.ProfileScreen.route,
    arguments = listOf(navArgument(name = ARGUEMENT1) {
    type = NavType.IntType
    })
    ) {
    Log.e("roshan",it.arguments?.getInt(ARGUEMENT1).toString())
    ProfileScreen(navController = navHostController)
    }


    You can also pass numeric value replacing old value
    fun passId(id:Int):String{
    return this.route.replace(oldValue = "{$ARGUEMENT1}", newValue = id.toString())
    }

    If you want to pass two arguements 

    const val ARGUEMENT1="id"
    const val ARGUEMENT2="name"
    sealed class Screens(val route: String) {

    data object HomeScreen : Screens("Home")
    data object ProfileScreen : Screens("Profile/{$ARGUEMENT1}/{$ARGUEMENT2}")
    /* fun passId(id:Int):String{
    return this.route.replace(oldValue = "{$ARGUEMENT1}", newValue = id.toString())
    }*/
    fun passIdName(id:Int,name:String):String{
    return "Profile/$id/$name"
    }
    data object DetailScreen : Screens("Details")

    }
    navController.navigate(Screens.ProfileScreen.passIdName(10,"Sukesh"))

    composable(
    route = Screens.ProfileScreen.route,
    arguments = listOf(
    navArgument(name = ARGUEMENT1) {
    type = NavType.IntType
    },
    navArgument(name = ARGUEMENT2) {
    type = NavType.StringType
    },
    ),
    ) {
    Log.e(
    "roshan",
    it.arguments?.getInt(ARGUEMENT1).toString() + "\n " + it.arguments?.getString(
    ARGUEMENT2
    ).toString()
    )
    ProfileScreen(navController = navHostController)
    }



    You can Pass nav arguements without using slash ("/")
    const val ARGUEMENT2="name"
    
    const val ARGUEMENT1="id"
      data object ProfileScreen : Screens("Profile?id={$ARGUEMENT1}?name={$ARGUEMENT2}")
    /* fun passId(id:Int):String{
    return this.route.replace(oldValue = "{$ARGUEMENT1}", newValue = id.toString())
    }*/
    fun passIdName(id:Int,name:String):String{
    return "Profile?id=$id?name=$name"
    }
    navController.navigate(Screens.ProfileScreen.passIdName(10,"Sukesh"))

    You can also use "&" for navArgs also take default value

    package com.example.jetpackcomposepractise.ui.theme.screens


    const val ARGUEMENT1="id"
    const val ARGUEMENT2="name"
    sealed class Screens(val route: String) {

    data object HomeScreen : Screens("Home")
    data object ProfileScreen : Screens("Profile?id={$ARGUEMENT1}&name={$ARGUEMENT2}")

    fun passIdName(id: Int? = null, name: String? = null): String {
    return "Profile?id=${id?.toString() ?: "0"}&name=$name"
    }

    data object DetailScreen : Screens("Details")
    }


    composable(
    route = Screens.ProfileScreen.route,
    arguments = listOf(
    navArgument(name = ARGUEMENT1) {
    type = NavType.StringType // Changed from IntType to StringType
    defaultValue = "0" // Provide default value as a String
    nullable = true
    },
    navArgument(name = ARGUEMENT2) {
    type = NavType.StringType
    defaultValue = "Roshan"
    nullable = true
    },
    ),
    ) {
    val idString = it.arguments?.getString(ARGUEMENT1) ?: "0"
    val id = idString.toIntOrNull() ?: 0 // Convert to Int or fallback to 0
    val name = it.arguments?.getString(ARGUEMENT2) ?: "Roshan"

    Log.e("Profile Args", "ID: $id, Name: $name")
    ProfileScreen(navController = navHostController)
    }

    navController.navigate(Screens.ProfileScreen.passIdName())



Post a Comment

0 Comments