Kenny Sexton
Kenny Sexton

Reputation: 383

Compose Navigation - Incompatibility and workaround with Serialized Objects

I have a project where I am using the material 3 top app bar. Naturally when I am on my home page, I want to hide the back button since there is nothing on the backstack. However, I am not using hardcoded routes and instead am using @Serializable objects.

import kotlinx.serialization.Serializable

@Serializable
object WeatherLanding

The issue is that this makes the logic for checking a little strange. Since the outcome of a common check of the current navgraph will output the full package name.

println(navController.currentDestination?.route)
// com.mypackage.projectname.WeatherLanding

Is there a good way to handle this? navController.currentDestination wants to output a string, but the whole point of creating navigation objects is to avoid string comparisons.

Upvotes: 3

Views: 182

Answers (1)

Kenny Sexton
Kenny Sexton

Reputation: 383

Here is a working solution, it is pretty messy. I am hoping there is a cleaner way to deal with updates to the navgraph without having to attach a listener and manually grabbing the package name via WeatherLanding::class.java.name, but I have not found any similar examples available yet.

Theme {
    val navController = rememberNavController()
    var showBackButton by rememberSaveable { mutableStateOf(false) }

    // NavController doesn't fire on update. Instead we have to attach this listener
    navController.addOnDestinationChangedListener { _, destination, arguments ->
        // Handle destination changes here
        showBackButton = when (destination.route) {
            WeatherLanding::class.java.name -> {
                false
            }

            else -> {
                true
            }
        }
    }

    Scaffold(
        topBar = {
            TitleBar(
                showBackButton = showBackButton,
                onBackButtonClicked = { navController.navigateUp() },
        },
        modifier = Modifier.fillMaxSize()
    ) { innerPadding ->
        NavHost(
            navController = navController,
            startDestination = WeatherLanding,
            modifier = Modifier.padding(innerPadding)
        ) {
            composable<WeatherLanding> {
                // Composable
            }
            composable<LocationSearch> {
                // Composable
            }
        }
    }
}

Upvotes: 0

Related Questions