Reputation: 63
I have Activity with hidden navigation bar and pure Compose content. It works as expected until androidx.compose.material3.DropdownMenu is shown. At this moment navbar is back, it hides again when menu is closed: GIF1. Then I did DropdownMenu(properties = PopupProperties(dismissOnBackPress = false))
. Now navbar pops up when menu appears and quickly hides back on its own with animation: GIF2.
@Composable
fun MenuSample(onSearch: () -> Unit) {
var expanded by remember { mutableStateOf(false) }
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
properties = PopupProperties(dismissOnBackPress = false)
) {
DropdownMenuItem(
text = { Text("Search") },
onClick = onSearch,
leadingIcon = {
Icon(
Icons.Outlined.Search,
contentDescription = null
)
})
}
}
Navbar absence is initially configured like this:
class MyActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Companion.window = window
hideNavBarAgain()
setContent { MyJetpackContent() }
}
companion object { //for experimentation purposes
var window: Window? = null
fun hideNavBarAgain() {
WindowInsetsControllerCompat(window!!, window!!.decorView).let { controller ->
controller.hide(WindowInsetsCompat.Type.navigationBars())
controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
}
}
}
}
properties = PopupProperties(dismissOnBackPress = false)
as DropdownMenu argument (my original finding)SideEffect { MyActivity.hideNavBarAgain() }
(suggested by @rafael-moreira), in every composable scope possible of MenuSample and also around it.rememberCoroutineScope.launch { MyActivity.hideNavBarAgain() }
in user click lambda that enables Menu. Also without coroutine scope in same place.Modifier.onPlaced { MyActivity.hideNavBarAgain() }
for both DropdownMenu and DropdownMenuItemExperiments matrix (navbar hidden in OnCreate() in all cases):
dismiss-false | SideEffect | remCorSc.launch | onPlaced | outcome |
---|---|---|---|---|
➖ | ➖ | ➖ | ➖ | 😣 permanent navbar GIF1 |
➕ | ➖ | ➖ | ➖ | 😕 jumpy navbar GIF2 |
➖ | ➕ | ➖ | ➖ | 😣 permanent navbar |
➖ | ➖ | ➕ | ➖ | 😣 permanent navbar |
➕ | ➕ | ➕ | ➕ | 😕 jumpy navbar |
It worth nothing, that all this is happening on MIUI 13. On relatively pure Android 14 (Nothing OS) none of this happens! 0 workarounds (➖|➖|➖) give missing navbar as expected, MyActivity config is enough.
How do I properly prevent navbar from showing at first place for all platforms?
Upvotes: 0
Views: 80
Reputation: 430
It's because DropDownMenu is considered a Pop-up in terms of behaviour. It's like the user is interacting with the screen.
Use the composable SideEffect to create a reaction with the DropDownMenu (from MenuSample) when is shown or not, to avoid displaying your navigation bar.
EXAMPLE:
Add SideEffect to your MenuSample function and the window object as a parameter when you call MenuSample. For more details, check the documentation.
@Composable
fun MenuSample(onSearch: () -> Unit, window: Window) {
var expanded by remember { mutableStateOf(false) }
SideEffect {
WindowInsetsControllerCompat(window, window.decorView).let { controller ->
controller.hide(WindowInsetsCompat.Type.navigationBars())
controller.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
}
}
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
properties = PopupProperties(dismissOnBackPress = false)
) {
DropdownMenuItem(
text = { Text("Search") },
onClick = onSearch,
leadingIcon = {
Icon(
Icons.Outlined.Search,
contentDescription = null
)
})
}
}
Upvotes: 0