You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 00:20:24