Android API 31下无法隐藏系统导航栏的技术求助
在Android API 31的.NET MAUI Kiosk模式中,阻止Picker/Popup触发系统导航栏弹出
问题描述
使用Picker或Community Toolkit的Popup等控件交互时,Android系统导航栏(底部三按钮)会自动弹出。应用需运行在Kiosk模式下,已成功隐藏状态栏,但导航栏始终无法保持隐藏状态。
Popup使用示例代码:
var pwdPopup = new SettingsPwdPopup(); // 创建弹窗并等待其关闭 object? pwd = await this.ShowPopupAsync(pwdPopup).ConfigureAwait(false); return pwd?.ToString();
已尝试但无效的方法:
- 使用
Shell.Current.GoToAsync();替代导航栈 - 设置Window Flags和SystemUiVisibility:
Window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen); Window.SetFlags(WindowManagerFlags.LayoutInScreen, WindowManagerFlags.LayoutInScreen); this.Window.DecorView.SystemUiVisibility = (StatusBarVisibility) (SystemUiFlags.ImmersiveSticky | SystemUiFlags.HideNavigation | SystemUiFlags.Fullscreen | SystemUiFlags.Immersive | SystemUiFlags.LayoutHideNavigation | SystemUiFlags.LayoutStable | SystemUiFlags.LowProfile);
- 添加
NavigationPage.HasNavigationBar="False"(使用NavigationPages时) - 在AppShell.xaml中设置
<Shell ... Shell.NavBarVisible="False"> - 在AppShell.xaml中配置BackButtonBehavior:
<?xml version="1.0" encoding="UTF-8" ?> <Shell ... Shell.NavBarIsVisible="False"> <Shell.BackButtonBehavior> <BackButtonBehavior IsVisible="False" IsEnabled="False"/> </Shell.BackButtonBehavior> <ShellContent ... /> </Shell>
- 使用WindowInsetsControllerCompat:
WindowCompat.SetDecorFitsSystemWindows(Window, false); WindowInsetsControllerCompat windowInsetsControllerCompat = ViewCompat.GetWindowInsetsController(Window.DecorView); windowInsetsControllerCompat.Hide(WindowInsetsCompat.Type.SystemBars() | WindowInsetsCompat.Type.NavigationBars()); windowInsetsControllerCompat.SystemBarsBehavior = WindowInsetsControllerCompat.BehaviorShowBarsBySwipe;
当前环境:
- Android API 31
- .NET MAUI 6.0.541
- CommunityToolkit.Maui 1.2.0
解决方案
控件交互触发导航栏弹出的核心原因是:Popup、Picker等控件会请求系统窗口焦点,打破之前设置的沉浸式状态。需通过以下方式重新锁定沉浸式模式:
1. 重写MainActivity的窗口焦点变化方法
在Android项目的MainActivity.cs中,重写OnWindowFocusChanged方法,每次窗口重新获得焦点时强制应用沉浸式设置:
protected override void OnWindowFocusChanged(bool hasFocus) { base.OnWindowFocusChanged(hasFocus); if (hasFocus) { ApplyImmersiveMode(); } } private void ApplyImmersiveMode() { var windowInsetsController = ViewCompat.GetWindowInsetsController(Window.DecorView); if (windowInsetsController != null) { windowInsetsController.Hide(WindowInsetsCompat.Type.SystemBars() | WindowInsetsCompat.Type.NavigationBars()); windowInsetsController.SystemBarsBehavior = WindowInsetsControllerCompat.BehaviorShowBarsBySwipe; } }
2. 为Popup添加焦点监听
在自定义Popup的代码中,监听焦点变化事件,确保弹窗显示/隐藏时重新应用沉浸式设置:
public partial class SettingsPwdPopup : Popup { public SettingsPwdPopup() { InitializeComponent(); Focused += (s, e) => ReapplyImmersiveMode(); Unfocused += (s, e) => ReapplyImmersiveMode(); } private void ReapplyImmersiveMode() { #if ANDROID var currentActivity = Platform.CurrentActivity; var insetsController = ViewCompat.GetWindowInsetsController(currentActivity.Window.DecorView); if (insetsController != null) { insetsController.Hide(WindowInsetsCompat.Type.SystemBars() | WindowInsetsCompat.Type.NavigationBars()); insetsController.SystemBarsBehavior = WindowInsetsControllerCompat.BehaviorShowBarsBySwipe; } #endif } }
3. 自定义Picker避免系统弹窗(可选)
如果Picker是触发源,可自定义Picker控件,使用MAUI内置的列表或弹窗替代系统默认选择器,彻底避免系统UI被触发。
4. 系统级Kiosk配置补充
通过Android设备管理器或EMM工具,将设备配置为完全Kiosk模式,禁用系统导航栏的手势触发逻辑,从系统层面锁定导航栏隐藏状态,配合应用层设置实现最佳效果。
内容的提问来源于stack exchange,提问作者Skyhighjinks
相关产品推荐
相关产品推荐

