kotlin - How to deal with Compose Desktop MenuBar - Stack Overflow
Welcome all
I want to add a windows top menu bar, like in windows applications. I found MenuBar, but... how to deal with navigation or logic in general in MenuBar
? All the screens of my application and navigation logic are on my commonMain
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:
.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.navigationpose.ComposeNavigator". You must call NavController.addNavigator() for each navigation type.
How can I solve it?
Welcome all
I want to add a windows top menu bar, like in windows applications. I found MenuBar, but... how to deal with navigation or logic in general in MenuBar
? All the screens of my application and navigation logic are on my commonMain
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.
How can I solve it?
Share Improve this question asked yesterday NullPointerExceptionNullPointerException 37.4k80 gold badges230 silver badges400 bronze badges1 Answer
Reset to default 0Is necessary to call rememberNavController inside the state holder:
navController: NavHostController = rememberNavController()
doing that, solves the issue, as done in nowinandroidapp:
@Composable
fun rememberNiaAppState(
navController: NavHostController = rememberNavController(),
): NiaAppState {
return remember(
navController
) {
NiaAppState(
navController = navController
)
}
}
@Stable
class NiaAppState(
val navController: NavHostController
)
- 安卓上市11年 为何说iPhone用户也要感谢它
- 研究机构:平板四年内将成主流计算设备
- 恶意软件侵害苹果用户!4G更易受攻击
- [连载]巨头“心血之作”终失败(五):惠普TouchPad
- spi - Interrupt safety of `HAL_SPI_TransmitReceive` - Stack Overflow
- azure active directory - Entra External Id: Include values provided by token requester in access token claims - Stack Overflow
- javascript - Alpine.js menu toggle issue - Stack Overflow
- React Native - Persist android ripple on state change - Stack Overflow
- verilog - Is it possible to create task within interface for specific modport? - Stack Overflow
- c# - After debugging, Visual Studio 2022 holding on to .NET Core program's .dll and I can't complete next build
- c# - How to add image as an input to a ChatMessage with Microsoft.Extensions.AI - Stack Overflow
- Why is my ESP32 task not logging when Wi-Fi is disconnected, but Wi-Fi retry logs are showing up? - Stack Overflow
- Stripe Connect, Register fake account on test mode - Stack Overflow
- Compare two lists, one of them JSON, in SQLite - Stack Overflow
- python - pickle port? loading a pickle with data when I've redefined the object code - Stack Overflow
- python - Galaga game not running due to an empty range - Stack Overflow
- Scene Appears Completely Black on Android Build Despite Correct UI Rendering in Unity Editor - Stack Overflow