Android 7+应用中彻底禁用状态栏与导航栏的实现方案问询
哥们,我太懂你这种烦恼了!之前用主题或者FLAG_FULLSCREEN确实只能临时隐藏系统栏,一滑就出来,根本达不到“彻底禁用”的效果。要实现真正的全屏锁定,得用上Android的沉浸式全屏模式,还要针对不同版本做适配,下面给你分版本讲具体实现:
一、Android 7.0 - Android 10(API 24~29)
这几个版本还在用setSystemUiVisibilityAPI,核心是把几个系统UI标志组合起来,并且在窗口获取焦点时重新设置(避免系统操作导致栏重新显示)。
1. 先配置Activity主题
在AndroidManifest.xml里给目标Activity设置全屏主题,确保基础的全屏属性生效:
<activity android:name=".YourFullscreenActivity" android:theme="@style/Theme.AppCompat.Light.NoActionBar.Fullscreen"> </activity>
对应的主题样式(在res/values/styles.xml里):
<style name="Theme.AppCompat.Light.NoActionBar.Fullscreen" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowFullscreen">true</item> <item name="android:windowContentOverlay">@null</item> </style>
2. 在Activity中设置沉浸式标志
重写onWindowFocusChanged方法,每次窗口获取焦点时强制隐藏系统栏并锁定:
@Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { View decorView = getWindow().getDecorView(); decorView.setSystemUiVisibility( // 让布局延伸到状态栏和导航栏后面 View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // 隐藏导航栏和状态栏 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN // 沉浸式模式:滑动栏区域不会直接显示,需要手动操作才会唤起 | View.SYSTEM_UI_FLAG_IMMERSIVE); } }
注意:如果用
SYSTEM_UI_FLAG_IMMERSIVE_STICKY,滑动后栏会临时显示然后自动隐藏;而SYSTEM_UI_FLAG_IMMERSIVE需要手动点击栏上的“返回”按钮才会隐藏,如果你要彻底不让滑动唤起,就用IMMERSIVE,并且确保每次焦点变化都重新设置。
3. 处理屏幕旋转等配置变化
如果你的Activity允许屏幕旋转,记得在onConfigurationChanged里重新设置系统UI:
@Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // 重新应用全屏设置 View decorView = getWindow().getDecorView(); decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE); }
别忘了在AndroidManifest.xml的Activity里加上配置变化声明:
<activity android:name=".YourFullscreenActivity" android:theme="@style/Theme.AppCompat.Light.NoActionBar.Fullscreen" android:configChanges="orientation|screenSize|keyboardHidden"> </activity>
二、Android 11+(API 30及以上)
从API30开始,setSystemUiVisibility被废弃了,官方推荐用WindowInsetsController来控制系统栏,更灵活。
1. 配置主题(和之前一致)
还是先给Activity设置全屏主题,确保基础属性正确。
2. 使用WindowInsetsController控制全屏
在Activity的onCreate或者onWindowFocusChanged里设置:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fullscreen); // 隐藏状态栏和导航栏 WindowInsetsController insetsController = getWindow().getInsetsController(); if (insetsController != null) { // 隐藏状态栏和导航栏 insetsController.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars()); // 设置行为:禁止通过滑动唤起系统栏,仅允许双击顶部显示 insetsController.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_TAP); } // 可选:保持屏幕常亮,避免锁屏后系统栏重新显示 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); }
3. 焦点变化的保险措施
和旧版本一样,在onWindowFocusChanged里重新隐藏系统栏,防止某些系统操作(比如弹出通知后)导致栏显示:
@Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { WindowInsetsController insetsController = getWindow().getInsetsController(); if (insetsController != null) { insetsController.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars()); } } }
三、额外注意事项
- 虚拟导航栏 vs 物理按键:如果设备是物理导航键,那没办法禁用,但虚拟导航栏可以通过上面的方法彻底隐藏。
- 系统权限:不需要额外权限,这些操作都是Activity级别的设置,只要你的应用是前台运行就生效。
- 厂商定制系统:部分厂商(如小米、华为)会定制系统UI,建议在目标设备上测试,上述方案是通用的基础实现。
内容的提问来源于stack exchange,提问作者DarkVss




