2

What i am trying to do is to close the TopBar dropdown menu after clicking the dropdown item. It can be easily done, if i am putting the dropdown items directly inside the dropdown menu. But here i am trying to separate it as a composable for readability.

Here is my TopAppBar

@Composable fun TopBar( scope: CoroutineScope, scaffoldState: ScaffoldState, event: (AdminLaunchEvents) -> Unit, navController: NavHostController ) { val openDialog = remember { mutableStateOf(false) } TopAppBar( title = { Text(text = "Main App Admin Area", fontSize = 18.sp) }, actions = { OverflowMenu() { SettingsDropDownItem(onClick = {}) ModeDropDownItem(onClick = {}) LogoutDropDownItem(onClick = { openDialog.value = true }) } }, backgroundColor = MaterialTheme.colors.primary, contentColor = Color.White ) if (openDialog.value) { LogOutComponent(openDialog = openDialog, event = event,navController = navController) } } 

And this is the OverFlowMenu composable which contains the DropDown Menu

@Composable fun OverflowMenu(content: @Composable () -> Unit) { var showMenu by remember { mutableStateOf(false) } IconButton(onClick = { showMenu = !showMenu }) { Icon( imageVector = Icons.Outlined.MoreVert, contentDescription = "More", ) } DropdownMenu( expanded = showMenu, onDismissRequest = { showMenu = false } ) { content() } } 

Now given below is the DropDownItem.

@Composable fun SettingsDropDownItem(onClick: () -> Unit) { DropdownMenuItem(onClick = onClick) { Icon( Icons.Filled.Settings, contentDescription = "Settings", modifier = Modifier.size(24.dp) ) Spacer(modifier = Modifier.width(8.dp)) Text("Settings") } } 

What i am trying to do is, when i click the SettingsDroDownItem, i need to capture the click event in the OverFlowMenu composable to make the showMenu false, so as the hide the DropdownMenu. I can get the click event in the TopAppBar, but how to get it on DropDownMenu.

How to do that?

1 Answer 1

5
  1. The first option is moving showMenu state out of OverflowMenu, as this is not the only composable which depends on the value. Something like this: OverFlowMenu:

    @Composable fun OverflowMenu(showMenu: Bool, setShowMenu: (Bool) -> Unit, content: @Composable () -> Unit) { // ... } 

    TopBar:

    actions = { var (showMenu, setShowMenu) = remember { mutableStateOf(false) } OverflowMenu(showMenu, setShowMenu) { SettingsDropDownItem(onClick = { openDialog.value = true setShowMenu(false) }) } }, 
  2. An other options is creating something like OverflowMenuScope, and running SettingsDropDownItem on this scope so it can close the menu itself: OverflowMenu:

    interface OverflowMenuScope { fun closeMenu() } @Composable fun OverflowMenu(content: @Composable OverflowMenuScope.() -> Unit) { var showMenu by remember { mutableStateOf(false) } val scope = remember { object: OverflowMenuScope { override fun closeMenu() { showMenu = false } } } //... DropdownMenu( expanded = showMenu, onDismissRequest = { showMenu = false } ) { scope.content() } } 

    SettingsDropDownItem:

    @Composable fun OverflowMenuScope.SettingsDropDownItem(onClick: () -> Unit) { DropdownMenuItem(onClick = { closeMenu() onClick() }) { Icon( Icons.Filled.Settings, contentDescription = "Settings", modifier = Modifier.size(24.dp) ) Spacer(modifier = Modifier.width(8.dp)) Text("Settings") } } 
Sign up to request clarification or add additional context in comments.

6 Comments

@shijilal could you confirmed what was the problem if any, with the first method? That's what I'd recommend
@MARSK Haven't tried that first one now. It is something i had tired previously, but couldn't get it working. Haven't tried to make it work. The second one seems to be a newer thing to me.. so tried that
@MARSK Why do you think, i should use the first method?
The first method is what you would actually use most of the time. I mean such scenarios are too common to create a scope for every single time you encounter them. The second method is just Philip's force of habit gone crazy. He loves way too overcomplicating things. Never mind.
@MARSK If you're creating SettingsDropDownItem to be used only inside OverflowMenu, the second method is much cleaner and the code is easier to read.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.