Pablo
01/04/2025, 11:26 AMAlex Styl
01/04/2025, 12:18 PMPablo
01/04/2025, 12:22 PMcommonMain
module. Navigation logic needs to be also present on my commonMain
screens because they can also navigate between them with buttons, the same navigation that must have the MenuBar
should be shared between MenuBar
and the screens buttons navigation. This is like when you access the "Window" or "Screen" sections of a windows app top menu bar, they allow you navigate, but you also can switch screens with some buttons in the UI of the windows application.
MenuBar
is a desktop only composable, so it must be created on the Window
of the desktopMain
module, before displaying any ui screen placed on the commonMain
module. If it needs to execute navigation
, it need to hold a instance of the navcontroller
, and to pass the navcontroller
down in the appstateholder
to the commonMain
module screens. I followed the pattern in nowinandroid
app:
https://github.com/android/nowinandroid/blob/d15c739812f25401b21614fe0f7e18534d285921/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaAppState.kt#L54
I created an appstateholder
class with the navcontroller
, and I instantiated that in the commonMain
package:
@Stable
class AppStateHolder(
val navController: NavHostController = NavHostController()
) {
// UI State
val currentDestination: NavDestination?
@Composable get() = navController
.currentBackStackEntryAsState().value?.destination
// UI logic
fun navigate(route: String) {
navController.navigate(route)
}
}
This is my desktopMain
window:
fun main() = application {
initKoin(
databaseBuilder = createDatabaseBuilder(),
)
val windowState = rememberWindowState(
size = DpSize(1200.dp, 900.dp),
position = WindowPosition(Alignment.Center)
)
val appStateHolder= remember { AppStateHolder() }
Window(
onCloseRequest = ::exitApplication,
title = stringResource(Res.string.app_name),
state = windowState
) {
WindowsMenuBar(
onNavigation = { route -> appStateHolder.navigate(route) },
onExitEvent = ::exitApplication
)
MyApplicationTheme {
App(appStateHolder)
}
}
}
Then, in my commonMain
package I receive that appStateHolder
and use it for navigation:
@Composable
fun App(appStateHolder: AppStateHolder) {
NavHost(
navController = appStateHolder.navController,
startDestination = ScreenRoute.MainScreen.name
) {
composable(ScreenRoute.MainScreen.name) {
MainScreen(
modifier = Modifier.padding(16.dp),
onBusStopsDBButtonClicked = { appStateHolder.navigate(ScreenRoute.BusStopsDB.name) }
)
}
Well, this doesn't work, and gives me this runtime error on composable(ScreenRoute.MainScreen.name)
line of my desktopMain
module:
> Navigator with class "class androidx.navigation.compose.ComposeNavigator". You must call NavController.addNavigator() for each navigation type.Chrimaeon
01/04/2025, 2:23 PMSanlorng
01/04/2025, 2:23 PMPablo
01/04/2025, 2:25 PMval appStateHolder= remember { AppStateHolder() }
Sanlorng
01/04/2025, 2:25 PMChrimaeon
01/04/2025, 2:25 PMrememberNavController
is doing some initialisation https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:navigati[…]vigation/compose/NavHostController.kt?q=rememberNavControllerChrimaeon
01/04/2025, 2:27 PMSanlorng
01/04/2025, 2:36 PMPablo
01/04/2025, 2:39 PMChrimaeon
01/04/2025, 2:40 PM