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

Android 11环境下如何彻底隐藏/禁用导航栏与状态栏?

Android 11下彻底隐藏/禁用导航栏与状态栏的解决方案

针对你遇到的普通沉浸式模式滑动后系统栏仍会弹出的问题,以下是几种可行的解决方向:

1. 设备所有者/配置文件所有者模式(最彻底的系统级限制)

Android 11中,只有拥有设备所有者或配置文件所有者权限的应用,才能真正禁用导航栏和状态栏。这种方式通过系统政策限制,用户无法通过滑动或其他操作调出系统栏。

实现步骤:

  • 首先将你的应用注册为设备所有者:
    可以通过ADB命令快速配置(适用于测试设备):

    dpm set-device-owner com.your.package/.YourDeviceAdminReceiver
    

    (需要先创建继承自DeviceAdminReceiver的广播接收器,并在Manifest中配置相应权限)

  • 调用DevicePolicyManager设置禁用规则:

    DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
    ComponentName adminComponent = new ComponentName(this, YourDeviceAdminReceiver.class);
    
    // 禁用状态栏
    dpm.addUserRestriction(adminComponent, UserManager.DISALLOW_STATUS_BAR);
    // 禁用导航栏
    dpm.addUserRestriction(adminComponent, UserManager.DISALLOW_NAVIGATION_BAR);
    

注意:这种方式需要设备的系统级权限,仅适用于企业设备、定制ROM设备或用户明确授权的场景。

2. 基于WindowInsetsController的沉浸式优化(API 30+适配)

你之前使用的SYSTEM_UI_FLAG系列常量在Android 11(API 30)已被弃用,官方推荐使用WindowInsetsController来控制系统栏显示。虽然无法完全阻止滑动调出,但可以做到调出后自动快速隐藏,且限制操作:

@Override
protected void onResume() {
    super.onResume();
    Window window = getWindow();
    WindowInsetsController controller = window.getInsetsController();
    if (controller != null) {
        // 隐藏状态栏和导航栏
        controller.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
        // 设置系统栏行为:禁止通过滑动触发显示(部分设备需测试适配)
        controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_NEVER_HIDE);
    }
    // 设置窗口全屏布局,避免系统栏弹出时挤压界面
    window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
}

// 监听窗口焦点,重新获取焦点时立刻隐藏系统栏
@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus) {
        Window window = getWindow();
        WindowInsetsController controller = window.getInsetsController();
        if (controller != null) {
            controller.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
        }
    }
}

3. 拦截边缘触摸事件(极端场景补充)

如果以上方法仍无法满足需求,可以尝试在Activity中拦截系统栏触发区域的触摸事件,阻止用户调出系统栏:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    int screenHeight = getResources().getDisplayMetrics().heightPixels;
    // 定义触发系统栏的边缘区域(可根据设备调整像素值)
    int edgeSize = 100;

    // 拦截顶部状态栏触发区域的触摸
    if (ev.getY() <= edgeSize) {
        return true;
    }
    // 拦截底部导航栏触发区域的触摸
    if (ev.getY() >= screenHeight - edgeSize) {
        return true;
    }
    // 部分设备支持左右边缘调出导航栏,可根据需要添加拦截逻辑
    return super.dispatchTouchEvent(ev);
}

注意:这种方法可能会影响正常的界面触摸操作,需要根据你的应用场景调整边缘区域的大小。


内容的提问来源于stack exchange,提问作者MOMO

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 03:42:35