Imagine the usual behavior of a toolbar in Android.
You define a Toolbar widget in the Activity, and can access it using onCreateOptionsMenu and onOptionsItemSelected inside your fragments.
However, something like this is not possible with normal Jetpack Compose, as there is no way of accessing the Toolbar that is defined in the Activity's Scaffold.
So think of this scenario. You have an Activity, with the Scaffold defined in it, and a NavHost inside that Scaffold. The NavHost contains all the sub-pages of your application (Other Composables). The title can be handled view the Navigation Destination Listener, what remains is the Actions of the Toolbar.
How would you change the toolbar actions depending on the current page/composables you're in? And handle clicks on these actions?
P.S : Using a Toolbar in each of the pages is not a solution, as it makes for a bad user experience when switching between animated pages, where the toolbar will disppear and reappear on each page.
I used an interface I named ToolbarController which contained callback methods that could set the value for the variable(s) used in the the call to scaffold's TopAppBar:
@Composable
fun MyApp(){
var toolbarTitle by remember{ mutableStateOf("") }
// ToolbarController would be some interface you have defined
val toolbarController = object: ToolbarController {
override fun setTitle(title: String){
toolbarTitle = title
}
}
Scaffold(
topBar = {
TopAppBar( title = { Text(text = toolbarTitle) } )
}
){
SomeScreen(toolbarController = toolbarController)
}
}
@Composable
fun SomeScreen(
toolbarController: ToolbarController
) {
//I'm not 100% sure I need to use an effect here, but I think so...
//And I'm not sure this is the right one. It is not a coroutine I call,
//but it of course works with normal calls. Also SideEffect runs on every
//recompose according to the docs, and that's not what we want.
//https://developer.android.com/jetpack/compose/side-effects
LaunchedEffect(true){
toolbarController.setTitle("Some screen title")
}
}
Edit: And it is easy to use it for any of the toolbar properties, you could create the interface like this:
interface ToolbarController{
fun configToolbar(
title: String = "",
navigationIcon: IconButton? = null,
actions: List<IconButton> = listOf()
)
}
The point is that you just make callback functions and run them in LaunchedEffect. That is one way to set toolbar properties from within a composable in the scaffold. The interface stuff is just a way to group these callbacks so it don't get too messy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With