Android 11+ React Native中如何隐藏Modal等组件的导航栏?
React Native Android 11+ 沉浸式导航栏问题修复
问题描述
已通过在MainActivity.java中添加代码实现大部分页面隐藏导航栏,但Android 11及以上版本中,弹出React Native的Modal、Alert或软键盘时,系统导航栏会重新显示,需要解决该问题以保持全程沉浸式效果。
解决方案
核心思路
针对Android 11+的WindowInsets机制,通过监听窗口状态变化、统一配置窗口属性,确保Modal、Alert弹出或软键盘激活时,导航栏始终保持隐藏状态。
修改后的完整代码
import android.os.Build; import android.view.View; import android.view.Window; import android.view.WindowInsets; import android.view.WindowInsetsController; import android.view.WindowManager; import androidx.annotation.NonNull; import com.facebook.react.ReactActivity; public class MainActivity extends ReactActivity { @Override protected void onStart() { super.onStart(); setupImmersiveMode(); } @Override protected void onResume() { super.onResume(); setupImmersiveMode(); } private void setupImmersiveMode() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { hideNavAndroid11(); // 监听窗口Insets变化,Modal/软键盘触发时重新隐藏导航栏 getWindow().getDecorView().setOnApplyWindowInsetsListener((v, insets) -> { hideNavAndroid11(); return v.onApplyWindowInsets(insets); }); } else { hideNavAndroid10(); getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(visibility -> { if ((visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) { hideNavAndroid10(); } }); } } public void hideNavAndroid11() { final Window window = getWindow(); try { runOnUiThread(() -> { WindowInsetsController insetsController = window.getInsetsController(); if (insetsController != null) { insetsController.hide(WindowInsets.Type.navigationBars() | WindowInsets.Type.statusBars()); insetsController.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); } // 让布局延伸到系统栏区域,避免底部留白 window.setFlags( WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS ); }); } catch (Exception e) { e.printStackTrace(); } } public void hideNavAndroid10() { try { runOnUiThread(() -> { final View decorView = getWindow().getDecorView(); decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY ); getWindow().setFlags( WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS ); }); } catch (Exception e) { e.printStackTrace(); } } // 窗口重新获得焦点时(如Modal关闭后),重新启用沉浸式模式 @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { setupImmersiveMode(); } } }
关键改动说明
- Insets变化监听:Android 11+中通过
setOnApplyWindowInsetsListener捕获Modal、Alert、软键盘触发的窗口状态变化,每次变化后重新执行隐藏导航栏逻辑。 - FLAG_LAYOUT_NO_LIMITS:强制窗口布局延伸到系统栏区域,避免导航栏隐藏后出现底部空白。
- onWindowFocusChanged:确保Modal关闭、页面重新获得焦点时,沉浸式模式自动恢复。
内容的提问来源于stack exchange,提问作者Żabojad
相关产品推荐
相关产品推荐

