Search code examples
androidkotlinresourcesandroid-jetpack-composejetpack-compose-navigation

Is it possible you can get the actual value of a string resource by calling it from a sealed class?


I want to add a string resource to my app in the topbar but when I call it a number appears and because it is a sealed class it does not let me implement stringResource or getString.

<resources>
    <string name="app_name">AppEsquema</string>
    <string name="app"><b>"Translator</b>"</string>
</resources>
sealed class Destinations(
    val route: String,
    val title: String,
    val icon: ImageVector
){
    //Bottom bar windows
    object Translate: Destinations(R.string.app.toString(), "Translate", Icons.Default.Translate)
    object Words: Destinations("Words", "Words", Icons.Default.Assignment)
    object Numbers: Destinations("Numbers", "Numbers", Icons.Default.FormatListNumbered)
}

enter image description here

I don't enter the string directly because the topbar changes the name when navigating the windows and I want it to be personalized.

this is the code for the change of title by window, if it works but it gets the name of the path of the window and the only solution I saw is to assign a string resource to the path to customize it.

enter image description here


Solution

  • You can capture the return value from backStackEntry and used it to check against your Destination's route parameter via when and have it return an explicit String

    var title by remember {
        mutableStateOf("")
    }
    
    LaunchedEffect(Unit){
         navController.currentBackStackEntryFlow.collect {
            title = it.destination.route.let { route ->
                when (route) {
                    Destinations.Translate.route -> {
                         "Translate"
                    }
                    Destinations.Words.route -> {
                         "Words"
                    }
                    Destinations.Numbers.route -> {
                        "Numbers"
                    } else -> {
                        "" // empty or your default title bar
                    }
                }
            }
        }
    }
    
    TopAppBar(
        title = {
            Text(text = title)
        }
    )
    

    or you can add an additional parameter to your Destination sealed class

    sealed class Destinations(
        @StringRes val stringRes: Int,
        val route: String,
        val title: String,
        val icon: ImageVector
    ) {
        object Translate: Destinations(R.string.translate_title, ...)
        object Words: Destinations(R.string.words_title, ...)
        object Numbers: Destinations(R.string.numbers_title, ...)
    }
    

    and in your LaunchEffect call

    ...
    
    val context = LocalContext.current
    
    LaunchedEffect(Unit){
        navController.currentBackStackEntryFlow.collect {
            title = context.getString(it.destination.route.let { route ->
                when (route) {
                    Destinations.Translate.route -> {
                        Destinations.Translate.stringRes
                    }
                    Destinations.Words.route -> {
                        Destinations.Words.stringRes
                    }
                    Destinations.Numbers.route -> {
                        Destinations.Numbers.stringRes
                    }
                    else -> {
                        // empty or your default/initial title
                        Destinations.Translate.stringRes
                    }
                }
            })
        }
    }
    
    ...