what's the right way to change the TopAppBar title...
# compose
o
what's the right way to change the TopAppBar title (or any other prop for that matter) dynamically from each screen? So right now I have 1 Scaffold which use and inside is the NavHost, passed to each
composable
inside is
scaffoldState
where I go
scaffoldstate.value.title = { Text("Screen A" }
and the primary Scaffold just populates its own topAppBar with MyAppBar(title = scaffoldState.title) but this causes a lot of jank when switching between bottom bar destinations and sometimes one screen ends up with the title of the other and it's just bad having 2 Scaffolds causes a visual effect where you can see them being swapped out, Now In Android does it really well but the code is so convoluted I couldn't really pin down even where the switch was happening
y
I usually do it by observing the current route from whatever navigation library being used. The benefits is that there's only one place mutating the value of the app bar title so it's much easier to reason with and you can do it without re-rendering the whole app bar.
o
Hm so a mutablestateOf that you pass to each composable in the path and they mutate it? I’d love an example to see
y
Not passing of
MutableState
to other composables ..but something like this
Copy code
val navController = rememberNavController()

Scaffold (
    appBar = {
        AppBar(
            title = {
                val navBackStackEntry by navController.currentBackStackEntryAsState()
                val currentDestination = navBackStackEntry?.destination?.route
                val title = when(currentDestination) {
                    "profile" -> "Profile"
                    "friendslist" -> "Friends"
                    else -> null
                }
                title?.let { Text(it) }
            }
        )
    }
) {
    NavHost(navController = navController, startDestination = "profile") {
        composable("profile") { Profile(/*...*/) }
        composable("friendslist") { FriendsList(/*...*/) }
    }
}
Where the title is a function of the current route instead of an input from a child composable.
o
Oh wow
That is clever!
Thank you
y
No probs..glad it helps 🙌
o
that's it, that's literally how Now In Android does it, thanks a lot Yousef
f
That's fine for the title. But what if you want custom action button for every screen? Really fast you start to have large when/if..else statements with code that should really belong to the individual screens.
Something like the React Portal API would be really cool for this.
o
yea true, what do you do in this case?
f
We use a Scaffold for each screen currently. But as mentioned this is not so nice in terms of animation because the top bar animates as well.
o
yea it does that flicker thing
f
(actually we still have fragment based navigation, so we need multiple scaffolds anyway)
Maybe someone from the compose team can comment if an api akin to react portals is something they are thinking about?
o
made this video that drills all 4 possible solutions to this, I would love to see if anyone can show anything better for this specific usecase (which is super common I believe)

https://youtu.be/zUdpVc5vTQE

959 Views