Android登录页Fragment隐藏ActionBar后自动弹出的原因及解决方法
问题原因
- 你当前使用的代码是控制系统状态栏、导航栏的沉浸显示逻辑,和应用自身的*ActionBar(应用标题栏)*属于两套独立的控制体系,你没有单独对ActionBar做隐藏配置的情况下,Fragment依附的Activity会按照自身默认配置自动恢复ActionBar的显示。
- 系统UI可见性标记容易被重置:Fragment生命周期切换(如回到前台触发onResume)、页面弹出弹窗/软键盘、用户点击屏幕边缘等场景都会清空你之前给DecorView设置的标记,导致系统栏和ActionBar恢复显示。
- Activity主题配置冲突:如果你的Activity使用了自带ActionBar的主题,即使你做了代码隐藏,主题的配置优先级更高,也会导致ActionBar自动弹出。
解决方案
1. 优先配置主题从根源避免ActionBar显示
给登录页对应的Activity设置无ActionBar的主题,直接在res/values/styles.xml中添加如下配置:
<style name="LoginActivityTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar"> <!-- 可选:配置全屏属性,搭配你的沉浸逻辑使用 --> <item name="android:windowFullscreen">true</item> <item name="android:statusBarColor">@android:color/transparent</item> </style>
之后在AndroidManifest.xml中给对应的Activity指定这个主题即可。
2. 补充代码隐藏逻辑,适配生命周期变化
如果需要动态控制ActionBar的显示隐藏,或者不方便修改主题,可以在Fragment的生命周期方法中添加如下代码,避免配置被重置:
@Override public void onResume() { super.onResume(); // 页面回到前台时重新设置隐藏逻辑 updateHideConfig(); // 监听系统UI可见性变化,被重置时自动重新隐藏 requireActivity().getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(visibility -> { if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { updateHideConfig(); } }); } private void updateHideConfig() { // 你原来的沉浸配置 requireActivity().getWindow().getDecorView().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_STICKY); // 新增:隐藏ActionBar的逻辑 ActionBar actionBar = ((AppCompatActivity) requireActivity()).getSupportActionBar(); if (actionBar != null) { actionBar.hide(); } } @Override public void onPause() { super.onPause(); // 离开页面时移除监听避免内存泄漏 requireActivity().getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(null); }
3. 高版本Android适配(Android 11及以上)
Android 11之后setSystemUiVisibility方法已废弃,建议使用官方推荐的WindowInsetsControllerAPI实现同样效果:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { WindowInsetsController insetsController = requireActivity().getWindow().getInsetsController(); if (insetsController != null) { // 隐藏状态栏和导航栏 insetsController.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars()); // 配置为沉浸式,滑动边缘才会临时显示系统栏 insetsController.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); } // 同样需要隐藏ActionBar ActionBar actionBar = ((AppCompatActivity) requireActivity()).getSupportActionBar(); if (actionBar != null) { actionBar.hide(); } }
内容的提问来源于stack exchange,提问作者ravi pathak
相关产品推荐
相关产品推荐

