Android全屏应用中Spinner触发后状态栏无法隐藏的解决咨询
Android 10全屏模式下Spinner触发状态栏弹出的解决方案
针对你在DJI遥控器上遇到的全屏模式下点击Spinner导致状态栏弹出且无法自动隐藏的问题,提供以下几个可行方案:
方案一:自定义Spinner,强制控制PopupWindow的窗口属性
默认Spinner的PopupWindow会请求系统UI焦点,导致状态栏弹出。通过自定义Spinner,在弹出PopupWindow时手动设置窗口flags,避免触发系统UI变化:
public class FullscreenSpinner extends Spinner { public FullscreenSpinner(Context context) { super(context); } public FullscreenSpinner(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean performClick() { boolean result = super.performClick(); // 尝试获取并修改PopupWindow的窗口属性 try { Field popupField = Spinner.class.getDeclaredField("mPopup"); popupField.setAccessible(true); Object popupInstance = popupField.get(this); if (popupInstance instanceof ListPopupWindow) { ListPopupWindow listPopup = (ListPopupWindow) popupInstance; Window popupWindow = listPopup.getPopupWindow().getWindow(); if (popupWindow != null) { // 设置窗口不显示状态栏,且不获取焦点避免触发系统UI popupWindow.setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE ); popupWindow.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); listPopup.getPopupWindow().update(); } } } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } // 弹出后立即重新锁定全屏 hideSystemUI(); return result; } }
将布局中的Spinner替换为自定义的FullscreenSpinner即可。
方案二:监听系统UI变化,自动重新隐藏状态栏
通过注册系统UI可见性监听器,一旦检测到状态栏弹出,立即重新应用全屏配置:
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // 初始化全屏状态 hideSystemUI(); // 监听系统UI变化 requireActivity().getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(visibility -> { // 检测到状态栏/导航栏显示时,立即重新隐藏 if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { hideSystemUI(); } }); } private void hideSystemUI() { Window window = requireActivity().getWindow(); View decorView = window.getDecorView(); // 设置沉浸式粘性全屏,确保滑动后自动隐藏 decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE ); // 额外设置Window flags加固全屏状态 window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); }
同时在Activity的onResume方法中调用hideSystemUI(),确保从后台返回时保持全屏。
方案三:使用Android 10+原生WindowInsetsController控制UI
Android 10及以上可以使用WindowInsetsController更精准地控制系统UI,兼容性更好:
private void hideSystemUI() { Window window = requireActivity().getWindow(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { WindowInsetsController insetsController = window.getInsetsController(); if (insetsController != null) { // 隐藏状态栏和导航栏 insetsController.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars()); // 设置仅通过滑动临时显示,松手后自动隐藏 insetsController.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); } } else { // 兼容Android 10的旧逻辑 View decorView = window.getDecorView(); decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE ); } window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); }
额外注意事项
- 在
AndroidManifest.xml中添加权限,确保应用有控制系统UI的权限:<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> - DJI遥控器可能有定制化系统,建议在
onWindowFocusChanged方法中也调用hideSystemUI(),确保窗口获取焦点时保持全屏。
内容的提问来源于stack exchange,提问作者Sean
相关产品推荐
相关产品推荐

