I am a beginner in Android development, and I couldn't find a good solution to this. So, I use Scaffold as a general screen composable:
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HabitsTrackerApp() {
val navHostController = rememberNavController()
val currentScreenContent = when (navHostController.currentBackStackEntry?.destination?.route) {
Screen.HabitTracks.route -> listOf(Screen.HabitTracks.icon, Screen.HabitTracks.title)
else -> listOf(Screen.HabitTracks.icon, Screen.HabitTracks.title)
}
Scaffold(
topBar = {
TopBar(currentScreenContent[0], currentScreenContent[1])
},
bottomBar = {
BottomBar(navHostController = navHostController)
}) {
Column(
modifier = Modifier
.padding(it)
.padding(dimensionResource(id = R.dimen.default_screen_padding))
) {
NavGraph(navHostController)
}
}
}
In the topBar parameter, I use custom TopBar composable, which is contained in another file:
@Composable
fun TopBar(@DrawableRes icon: Int, @StringRes text: Int) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.padding(dimensionResource(id = R.dimen.padding_small))
) {
Icon(
imageVector = Icons.Rounded.ArrowBackIos,
contentDescription = stringResource(id = R.string.backward_icon_content_description)
)
Icon(
painter = painterResource(id = icon),
contentDescription = null,
modifier = Modifier
.size(dimensionResource(id = R.dimen.default_top_bar_icon_size))
.padding(end = dimensionResource(id = R.dimen.padding_medium))
)
Text(text = stringResource(id = text), style = MaterialTheme.typography.headlineLarge)
Icon(
imageVector = Icons.Rounded.ArrowForwardIos,
contentDescription = stringResource(id = R.string.forward_icon_content_description)
)
}
}
This TopBar composable requires the icon and header of the current screen. Right now, I use when statement (1st code block) to get current screen icon and text depending on the current navHostController route, but I'm sure that there's a much better solution. There's no way that writing when branches for each screen manually is a good way to solve this problem
NavGraph is also contained in a separate file, as well as each screen composable, if it is important
I initially thought about some kind of viewModel, which could contain the current icon and text of the composable as state, but, as far as i know, there's no way to get the same object of this exact vm and change the state in each screen composable unless I pass it as a parameter, which is also a bad solution
I also tried to google it and found only this, but maybe something changed 2 years later How to change topBar corresponding screen in Jetpack Compose
Or maybe the best way is to somehow change the project structure or something else? And how exactly?
P.S. sorry for my bad english